?????????? ????????? - ??????????????? - /home/agenciai/public_html/cd38d8/Arguments.tar
???????
Contract/ReplaceArgumentDefaultValueInterface.php 0000644 00000000470 15126475523 0016246 0 ustar 00 <?php declare (strict_types=1); namespace Rector\Arguments\Contract; interface ReplaceArgumentDefaultValueInterface { public function getPosition() : int; /** * @return mixed */ public function getValueBefore(); /** * @return mixed */ public function getValueAfter(); } ValueObject/RemoveMethodCallParam.php 0000644 00000001750 15126475523 0013650 0 ustar 00 <?php declare (strict_types=1); namespace Rector\Arguments\ValueObject; use PHPStan\Type\ObjectType; use Rector\Validation\RectorAssert; final class RemoveMethodCallParam { /** * @readonly * @var string */ private $class; /** * @readonly * @var string */ private $methodName; /** * @readonly * @var int */ private $paramPosition; public function __construct(string $class, string $methodName, int $paramPosition) { $this->class = $class; $this->methodName = $methodName; $this->paramPosition = $paramPosition; RectorAssert::className($class); RectorAssert::methodName($methodName); } public function getObjectType() : ObjectType { return new ObjectType($this->class); } public function getMethodName() : string { return $this->methodName; } public function getParamPosition() : int { return $this->paramPosition; } } ValueObject/ArgumentAdder.php 0000644 00000003775 15126475523 0012230 0 ustar 00 <?php declare (strict_types=1); namespace Rector\Arguments\ValueObject; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use Rector\Validation\RectorAssert; final class ArgumentAdder { /** * @readonly * @var string */ private $class; /** * @readonly * @var string */ private $method; /** * @readonly * @var int */ private $position; /** * @readonly * @var string|null */ private $argumentName; /** * @var mixed|null */ private $argumentDefaultValue = null; /** * @readonly * @var \PHPStan\Type\Type|null */ private $argumentType = null; /** * @readonly * @var string|null */ private $scope; /** * @param mixed|null $argumentDefaultValue */ public function __construct(string $class, string $method, int $position, ?string $argumentName = null, $argumentDefaultValue = null, ?\PHPStan\Type\Type $argumentType = null, ?string $scope = null) { $this->class = $class; $this->method = $method; $this->position = $position; $this->argumentName = $argumentName; $this->argumentDefaultValue = $argumentDefaultValue; $this->argumentType = $argumentType; $this->scope = $scope; RectorAssert::className($class); } public function getObjectType() : ObjectType { return new ObjectType($this->class); } public function getMethod() : string { return $this->method; } public function getPosition() : int { return $this->position; } public function getArgumentName() : ?string { return $this->argumentName; } /** * @return mixed|null */ public function getArgumentDefaultValue() { return $this->argumentDefaultValue; } public function getArgumentType() : ?Type { return $this->argumentType; } public function getScope() : ?string { return $this->scope; } } ValueObject/ReplaceArgumentDefaultValue.php 0000644 00000003317 15126475523 0015056 0 ustar 00 <?php declare (strict_types=1); namespace Rector\Arguments\ValueObject; use PHPStan\Type\ObjectType; use Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface; use Rector\Validation\RectorAssert; final class ReplaceArgumentDefaultValue implements ReplaceArgumentDefaultValueInterface { /** * @readonly * @var string */ private $class; /** * @readonly * @var string */ private $method; /** * @var int<0, max> * @readonly */ private $position; /** * @readonly * @var mixed */ private $valueBefore; /** * @readonly * @var mixed */ private $valueAfter; /** * @var string */ public const ANY_VALUE_BEFORE = '*ANY_VALUE_BEFORE*'; /** * @param int<0, max> $position * @param mixed $valueBefore * @param mixed $valueAfter */ public function __construct(string $class, string $method, int $position, $valueBefore, $valueAfter) { $this->class = $class; $this->method = $method; $this->position = $position; $this->valueBefore = $valueBefore; $this->valueAfter = $valueAfter; RectorAssert::className($class); } public function getObjectType() : ObjectType { return new ObjectType($this->class); } public function getMethod() : string { return $this->method; } public function getPosition() : int { return $this->position; } /** * @return mixed */ public function getValueBefore() { return $this->valueBefore; } /** * @return mixed */ public function getValueAfter() { return $this->valueAfter; } } ValueObject/ReplaceFuncCallArgumentDefaultValue.php 0000644 00000002420 15126475523 0016460 0 ustar 00 <?php declare (strict_types=1); namespace Rector\Arguments\ValueObject; use Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface; final class ReplaceFuncCallArgumentDefaultValue implements ReplaceArgumentDefaultValueInterface { /** * @readonly * @var string */ private $function; /** * @readonly * @var int */ private $position; /** * @readonly * @var mixed */ private $valueBefore; /** * @readonly * @var mixed */ private $valueAfter; /** * @param mixed $valueBefore * @param mixed $valueAfter */ public function __construct(string $function, int $position, $valueBefore, $valueAfter) { $this->function = $function; $this->position = $position; $this->valueBefore = $valueBefore; $this->valueAfter = $valueAfter; } public function getFunction() : string { return $this->function; } public function getPosition() : int { return $this->position; } /** * @return mixed */ public function getValueBefore() { return $this->valueBefore; } /** * @return mixed */ public function getValueAfter() { return $this->valueAfter; } } ValueObject/ArgumentAdderWithoutDefaultValue.php 0000644 00000003225 15126475523 0016104 0 ustar 00 <?php declare (strict_types=1); namespace Rector\Arguments\ValueObject; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use Rector\Validation\RectorAssert; final class ArgumentAdderWithoutDefaultValue { /** * @readonly * @var string */ private $class; /** * @readonly * @var string */ private $method; /** * @readonly * @var int */ private $position; /** * @readonly * @var string|null */ private $argumentName; /** * @readonly * @var \PHPStan\Type\Type|null */ private $argumentType = null; /** * @readonly * @var string|null */ private $scope; public function __construct(string $class, string $method, int $position, ?string $argumentName = null, ?\PHPStan\Type\Type $argumentType = null, ?string $scope = null) { $this->class = $class; $this->method = $method; $this->position = $position; $this->argumentName = $argumentName; $this->argumentType = $argumentType; $this->scope = $scope; RectorAssert::className($class); } public function getObjectType() : ObjectType { return new ObjectType($this->class); } public function getMethod() : string { return $this->method; } public function getPosition() : int { return $this->position; } public function getArgumentName() : ?string { return $this->argumentName; } public function getArgumentType() : ?Type { return $this->argumentType; } public function getScope() : ?string { return $this->scope; } } NodeAnalyzer/ChangedArgumentsDetector.php 0000644 00000003234 15126475523 0014575 0 ustar 00 <?php declare (strict_types=1); namespace Rector\Arguments\NodeAnalyzer; use PhpParser\Node\Expr; use PhpParser\Node\Param; use PHPStan\Type\Type; use Rector\NodeTypeResolver\TypeComparator\TypeComparator; use Rector\PhpParser\Node\Value\ValueResolver; use Rector\StaticTypeMapper\StaticTypeMapper; final class ChangedArgumentsDetector { /** * @readonly * @var \Rector\PhpParser\Node\Value\ValueResolver */ private $valueResolver; /** * @readonly * @var \Rector\StaticTypeMapper\StaticTypeMapper */ private $staticTypeMapper; /** * @readonly * @var \Rector\NodeTypeResolver\TypeComparator\TypeComparator */ private $typeComparator; public function __construct(ValueResolver $valueResolver, StaticTypeMapper $staticTypeMapper, TypeComparator $typeComparator) { $this->valueResolver = $valueResolver; $this->staticTypeMapper = $staticTypeMapper; $this->typeComparator = $typeComparator; } /** * @param mixed $value */ public function isDefaultValueChanged(Param $param, $value) : bool { if (!$param->default instanceof Expr) { return \false; } return !$this->valueResolver->isValue($param->default, $value); } public function isTypeChanged(Param $param, ?Type $newType) : bool { if ($param->type === null) { return \false; } if (!$newType instanceof Type) { return \true; } $currentParamType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($param->type); return !$this->typeComparator->areTypesEqual($currentParamType, $newType); } } NodeAnalyzer/ArgumentAddingScope.php 0000644 00000003455 15126475523 0013554 0 ustar 00 <?php declare (strict_types=1); namespace Rector\Arguments\NodeAnalyzer; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Name; use Rector\Arguments\ValueObject\ArgumentAdder; use Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue; use Rector\Enum\ObjectReference; use Rector\NodeNameResolver\NodeNameResolver; final class ArgumentAddingScope { /** * @readonly * @var \Rector\NodeNameResolver\NodeNameResolver */ private $nodeNameResolver; /** * @api * @var string */ public const SCOPE_PARENT_CALL = 'parent_call'; /** * @api * @var string */ public const SCOPE_METHOD_CALL = 'method_call'; /** * @api * @var string */ public const SCOPE_CLASS_METHOD = 'class_method'; public function __construct(NodeNameResolver $nodeNameResolver) { $this->nodeNameResolver = $nodeNameResolver; } /** * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $expr * @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder */ public function isInCorrectScope($expr, $argumentAdder) : bool { if ($argumentAdder->getScope() === null) { return \true; } $scope = $argumentAdder->getScope(); if ($expr instanceof StaticCall) { if (!$expr->class instanceof Name) { return \false; } if ($this->nodeNameResolver->isName($expr->class, ObjectReference::PARENT)) { return $scope === self::SCOPE_PARENT_CALL; } return $scope === self::SCOPE_METHOD_CALL; } // MethodCall return $scope === self::SCOPE_METHOD_CALL; } } Rector/MethodCall/RemoveMethodCallParamRector.php 0000644 00000006034 15126475523 0016076 0 ustar 00 <?php declare (strict_types=1); namespace Rector\Arguments\Rector\MethodCall; use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\StaticCall; use Rector\Arguments\ValueObject\RemoveMethodCallParam; use Rector\Contract\Rector\ConfigurableRectorInterface; use Rector\Rector\AbstractRector; use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; use RectorPrefix202411\Webmozart\Assert\Assert; /** * @see \Rector\Tests\Arguments\Rector\MethodCall\RemoveMethodCallParamRector\RemoveMethodCallParamRectorTest */ final class RemoveMethodCallParamRector extends AbstractRector implements ConfigurableRectorInterface { /** * @var RemoveMethodCallParam[] */ private $removeMethodCallParams = []; public function getRuleDefinition() : RuleDefinition { return new RuleDefinition('Remove parameter of method call', [new ConfiguredCodeSample(<<<'CODE_SAMPLE' final class SomeClass { public function run(Caller $caller) { $caller->process(1, 2); } } CODE_SAMPLE , <<<'CODE_SAMPLE' final class SomeClass { public function run(Caller $caller) { $caller->process(1); } } CODE_SAMPLE , [new RemoveMethodCallParam('Caller', 'process', 1)])]); } /** * @return array<class-string<Node>> */ public function getNodeTypes() : array { return [MethodCall::class, StaticCall::class]; } /** * @param MethodCall|StaticCall $node */ public function refactor(Node $node) : ?Node { $hasChanged = \false; if ($node->isFirstClassCallable()) { return null; } foreach ($this->removeMethodCallParams as $removeMethodCallParam) { if (!$this->isName($node->name, $removeMethodCallParam->getMethodName())) { continue; } if (!$this->isCallerObjectType($node, $removeMethodCallParam)) { continue; } $args = $node->getArgs(); if (!isset($args[$removeMethodCallParam->getParamPosition()])) { continue; } unset($node->args[$removeMethodCallParam->getParamPosition()]); $hasChanged = \true; } if (!$hasChanged) { return null; } return $node; } /** * @param mixed[] $configuration */ public function configure(array $configuration) : void { Assert::allIsInstanceOf($configuration, RemoveMethodCallParam::class); $this->removeMethodCallParams = $configuration; } /** * @param \PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\MethodCall $call */ private function isCallerObjectType($call, RemoveMethodCallParam $removeMethodCallParam) : bool { if ($call instanceof MethodCall) { return $this->isObjectType($call->var, $removeMethodCallParam->getObjectType()); } return $this->isObjectType($call->class, $removeMethodCallParam->getObjectType()); } } Rector/ClassMethod/ReplaceArgumentDefaultValueRector.php 0000644 00000010034 15126475523 0017470 0 ustar 00 <?php declare (strict_types=1); namespace Rector\Arguments\Rector\ClassMethod; use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\New_; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Stmt\ClassMethod; use Rector\Arguments\ArgumentDefaultValueReplacer; use Rector\Arguments\ValueObject\ReplaceArgumentDefaultValue; use Rector\Contract\Rector\ConfigurableRectorInterface; use Rector\Rector\AbstractRector; use Rector\ValueObject\MethodName; use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; use RectorPrefix202411\Webmozart\Assert\Assert; /** * @api used in rector-symfony * @see \Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\ReplaceArgumentDefaultValueRectorTest */ final class ReplaceArgumentDefaultValueRector extends AbstractRector implements ConfigurableRectorInterface { /** * @readonly * @var \Rector\Arguments\ArgumentDefaultValueReplacer */ private $argumentDefaultValueReplacer; /** * @var ReplaceArgumentDefaultValue[] */ private $replaceArgumentDefaultValues = []; public function __construct(ArgumentDefaultValueReplacer $argumentDefaultValueReplacer) { $this->argumentDefaultValueReplacer = $argumentDefaultValueReplacer; } public function getRuleDefinition() : RuleDefinition { return new RuleDefinition('Replaces defined map of arguments in defined methods and their calls.', [new ConfiguredCodeSample(<<<'CODE_SAMPLE' $someObject = new SomeClass; $someObject->someMethod(SomeClass::OLD_CONSTANT); CODE_SAMPLE , <<<'CODE_SAMPLE' $someObject = new SomeClass; $someObject->someMethod(false); CODE_SAMPLE , [new ReplaceArgumentDefaultValue('SomeClass', 'someMethod', 0, 'SomeClass::OLD_CONSTANT', \false)])]); } /** * @return array<class-string<Node>> */ public function getNodeTypes() : array { return [MethodCall::class, StaticCall::class, ClassMethod::class, New_::class]; } /** * @param MethodCall|StaticCall|ClassMethod|New_ $node * @return \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\New_|null */ public function refactor(Node $node) { $hasChanged = \false; if ($node instanceof New_) { return $this->refactorNew($node); } $nodeName = $this->getName($node->name); if ($nodeName === null) { return null; } foreach ($this->replaceArgumentDefaultValues as $replaceArgumentDefaultValue) { if (!$this->nodeNameResolver->isStringName($nodeName, $replaceArgumentDefaultValue->getMethod())) { continue; } if (!$this->nodeTypeResolver->isMethodStaticCallOrClassMethodObjectType($node, $replaceArgumentDefaultValue->getObjectType())) { continue; } $replacedNode = $this->argumentDefaultValueReplacer->processReplaces($node, $replaceArgumentDefaultValue); if ($replacedNode instanceof Node) { $hasChanged = \true; } } if ($hasChanged) { return $node; } return null; } /** * @param mixed[] $configuration */ public function configure(array $configuration) : void { Assert::allIsAOf($configuration, ReplaceArgumentDefaultValue::class); $this->replaceArgumentDefaultValues = $configuration; } private function refactorNew(New_ $new) : ?New_ { foreach ($this->replaceArgumentDefaultValues as $replaceArgumentDefaultValue) { if ($replaceArgumentDefaultValue->getMethod() !== MethodName::CONSTRUCT) { continue; } if (!$this->isObjectType($new, $replaceArgumentDefaultValue->getObjectType())) { continue; } return $this->argumentDefaultValueReplacer->processReplaces($new, $replaceArgumentDefaultValue); } return null; } } Rector/ClassMethod/ArgumentAdderRector.php 0000644 00000031110 15126475523 0014630 0 ustar 00 <?php declare (strict_types=1); namespace Rector\Arguments\Rector\ClassMethod; use PhpParser\BuilderHelpers; use PhpParser\Node; use PhpParser\Node\Arg; use PhpParser\Node\Expr; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Name; use PhpParser\Node\Param; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use Rector\Arguments\NodeAnalyzer\ArgumentAddingScope; use Rector\Arguments\NodeAnalyzer\ChangedArgumentsDetector; use Rector\Arguments\ValueObject\ArgumentAdder; use Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue; use Rector\Contract\Rector\ConfigurableRectorInterface; use Rector\Enum\ObjectReference; use Rector\Exception\ShouldNotHappenException; use Rector\PhpParser\AstResolver; use Rector\PHPStanStaticTypeMapper\Enum\TypeKind; use Rector\Rector\AbstractRector; use Rector\StaticTypeMapper\StaticTypeMapper; use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; use RectorPrefix202411\Webmozart\Assert\Assert; /** * @see \Rector\Tests\Arguments\Rector\ClassMethod\ArgumentAdderRector\ArgumentAdderRectorTest */ final class ArgumentAdderRector extends AbstractRector implements ConfigurableRectorInterface { /** * @readonly * @var \Rector\Arguments\NodeAnalyzer\ArgumentAddingScope */ private $argumentAddingScope; /** * @readonly * @var \Rector\Arguments\NodeAnalyzer\ChangedArgumentsDetector */ private $changedArgumentsDetector; /** * @readonly * @var \Rector\PhpParser\AstResolver */ private $astResolver; /** * @readonly * @var \Rector\StaticTypeMapper\StaticTypeMapper */ private $staticTypeMapper; /** * @var ArgumentAdder[]|ArgumentAdderWithoutDefaultValue[] */ private $addedArguments = []; /** * @var bool */ private $hasChanged = \false; public function __construct(ArgumentAddingScope $argumentAddingScope, ChangedArgumentsDetector $changedArgumentsDetector, AstResolver $astResolver, StaticTypeMapper $staticTypeMapper) { $this->argumentAddingScope = $argumentAddingScope; $this->changedArgumentsDetector = $changedArgumentsDetector; $this->astResolver = $astResolver; $this->staticTypeMapper = $staticTypeMapper; } public function getRuleDefinition() : RuleDefinition { return new RuleDefinition('This Rector adds new default arguments in calls of defined methods and class types.', [new ConfiguredCodeSample(<<<'CODE_SAMPLE' $someObject = new SomeExampleClass; $someObject->someMethod(); class MyCustomClass extends SomeExampleClass { public function someMethod() { } } CODE_SAMPLE , <<<'CODE_SAMPLE' $someObject = new SomeExampleClass; $someObject->someMethod(true); class MyCustomClass extends SomeExampleClass { public function someMethod($value = true) { } } CODE_SAMPLE , [new ArgumentAdder('SomeExampleClass', 'someMethod', 0, 'someArgument', \true, new ObjectType('SomeType'))])]); } /** * @return array<class-string<Node>> */ public function getNodeTypes() : array { return [MethodCall::class, StaticCall::class, Class_::class]; } /** * @param MethodCall|StaticCall|Class_ $node * @return \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Stmt\Class_|null */ public function refactor(Node $node) { $this->hasChanged = \false; if ($node instanceof MethodCall || $node instanceof StaticCall) { $this->refactorCall($node); } else { foreach ($node->getMethods() as $classMethod) { $this->refactorClassMethod($node, $classMethod); } } if ($this->hasChanged) { return $node; } return null; } /** * @param mixed[] $configuration */ public function configure(array $configuration) : void { Assert::allIsAnyOf($configuration, [ArgumentAdder::class, ArgumentAdderWithoutDefaultValue::class]); $this->addedArguments = $configuration; } /** * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $call */ private function isObjectTypeMatch($call, ObjectType $objectType) : bool { if ($call instanceof MethodCall) { return $this->isObjectType($call->var, $objectType); } return $this->isObjectType($call->class, $objectType); } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $node * @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder */ private function processPositionWithDefaultValues($node, $argumentAdder) : void { if ($this->shouldSkipParameter($node, $argumentAdder)) { return; } $argumentType = $argumentAdder->getArgumentType(); $position = $argumentAdder->getPosition(); if ($node instanceof ClassMethod) { $this->addClassMethodParam($node, $argumentAdder, $argumentType, $position); return; } if ($node instanceof StaticCall) { $this->processStaticCall($node, $position, $argumentAdder); return; } $this->processMethodCall($node, $argumentAdder, $position); } /** * @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder */ private function processMethodCall(MethodCall $methodCall, $argumentAdder, int $position) : void { if ($argumentAdder instanceof ArgumentAdderWithoutDefaultValue) { return; } $defaultValue = $argumentAdder->getArgumentDefaultValue(); $arg = new Arg(BuilderHelpers::normalizeValue($defaultValue)); if (isset($methodCall->args[$position])) { return; } $this->fillGapBetweenWithDefaultValue($methodCall, $position); $methodCall->args[$position] = $arg; $this->hasChanged = \true; } /** * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $node */ private function fillGapBetweenWithDefaultValue($node, int $position) : void { $lastPosition = \count($node->getArgs()) - 1; if ($position <= $lastPosition) { return; } if ($position - $lastPosition === 1) { return; } $classMethod = $this->astResolver->resolveClassMethodFromCall($node); if (!$classMethod instanceof ClassMethod) { return; } for ($index = $lastPosition + 1; $index < $position; ++$index) { $param = $classMethod->params[$index]; if (!$param->default instanceof Expr) { throw new ShouldNotHappenException('Previous position does not have default value'); } $node->args[$index] = new Arg($this->nodeFactory->createReprintedNode($param->default)); } } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $node * @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder */ private function shouldSkipParameter($node, $argumentAdder) : bool { $position = $argumentAdder->getPosition(); $argumentName = $argumentAdder->getArgumentName(); if ($argumentName === null) { return \true; } if ($node instanceof ClassMethod) { // already added? if (!isset($node->params[$position])) { return \false; } $param = $node->params[$position]; // argument added and name has been changed if (!$this->isName($param, $argumentName)) { return \true; } // argument added and default has been changed if ($this->isDefaultValueChanged($argumentAdder, $node, $position)) { return \true; } // argument added and type has been changed return $this->changedArgumentsDetector->isTypeChanged($param, $argumentAdder->getArgumentType()); } if (isset($node->args[$position])) { return \true; } // Check if default value is the same $classMethod = $this->astResolver->resolveClassMethodFromCall($node); if (!$classMethod instanceof ClassMethod) { // is correct scope? return !$this->argumentAddingScope->isInCorrectScope($node, $argumentAdder); } if (!isset($classMethod->params[$position])) { // is correct scope? return !$this->argumentAddingScope->isInCorrectScope($node, $argumentAdder); } if ($this->isDefaultValueChanged($argumentAdder, $classMethod, $position)) { // is correct scope? return !$this->argumentAddingScope->isInCorrectScope($node, $argumentAdder); } return \true; } /** * @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder */ private function isDefaultValueChanged($argumentAdder, ClassMethod $classMethod, int $position) : bool { return $argumentAdder instanceof ArgumentAdder && $this->changedArgumentsDetector->isDefaultValueChanged($classMethod->params[$position], $argumentAdder->getArgumentDefaultValue()); } /** * @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder */ private function addClassMethodParam(ClassMethod $classMethod, $argumentAdder, ?Type $type, int $position) : void { $argumentName = $argumentAdder->getArgumentName(); if ($argumentName === null) { throw new ShouldNotHappenException(); } if ($argumentAdder instanceof ArgumentAdder) { $param = new Param(new Variable($argumentName), BuilderHelpers::normalizeValue($argumentAdder->getArgumentDefaultValue())); } else { $param = new Param(new Variable($argumentName)); } if ($type instanceof Type) { $param->type = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($type, TypeKind::PARAM); } $classMethod->params[$position] = $param; $this->hasChanged = \true; } /** * @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder */ private function processStaticCall(StaticCall $staticCall, int $position, $argumentAdder) : void { if ($argumentAdder instanceof ArgumentAdderWithoutDefaultValue) { return; } $argumentName = $argumentAdder->getArgumentName(); if ($argumentName === null) { throw new ShouldNotHappenException(); } if (!$staticCall->class instanceof Name) { return; } if (!$this->isName($staticCall->class, ObjectReference::PARENT)) { return; } $this->fillGapBetweenWithDefaultValue($staticCall, $position); $staticCall->args[$position] = new Arg(new Variable($argumentName)); $this->hasChanged = \true; } /** * @param \PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\MethodCall $call */ private function refactorCall($call) : void { $callName = $this->getName($call->name); if ($callName === null) { return; } foreach ($this->addedArguments as $addedArgument) { if (!$this->nodeNameResolver->isStringName($callName, $addedArgument->getMethod())) { continue; } if (!$this->isObjectTypeMatch($call, $addedArgument->getObjectType())) { continue; } $this->processPositionWithDefaultValues($call, $addedArgument); } } private function refactorClassMethod(Class_ $class, ClassMethod $classMethod) : void { foreach ($this->addedArguments as $addedArgument) { if (!$this->isName($classMethod, $addedArgument->getMethod())) { continue; } if (!$this->isObjectType($class, $addedArgument->getObjectType())) { continue; } $this->processPositionWithDefaultValues($classMethod, $addedArgument); } } } Rector/FuncCall/FunctionArgumentDefaultValueReplacerRector.php 0000644 00000005201 15126475523 0020641 0 ustar 00 <?php declare (strict_types=1); namespace Rector\Arguments\Rector\FuncCall; use PhpParser\Node; use PhpParser\Node\Expr\FuncCall; use Rector\Arguments\ArgumentDefaultValueReplacer; use Rector\Arguments\ValueObject\ReplaceFuncCallArgumentDefaultValue; use Rector\Contract\Rector\ConfigurableRectorInterface; use Rector\Rector\AbstractRector; use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; use RectorPrefix202411\Webmozart\Assert\Assert; /** * @see \Rector\Tests\Arguments\Rector\FuncCall\FunctionArgumentDefaultValueReplacerRector\FunctionArgumentDefaultValueReplacerRectorTest */ final class FunctionArgumentDefaultValueReplacerRector extends AbstractRector implements ConfigurableRectorInterface { /** * @readonly * @var \Rector\Arguments\ArgumentDefaultValueReplacer */ private $argumentDefaultValueReplacer; /** * @var ReplaceFuncCallArgumentDefaultValue[] */ private $replacedArguments = []; public function __construct(ArgumentDefaultValueReplacer $argumentDefaultValueReplacer) { $this->argumentDefaultValueReplacer = $argumentDefaultValueReplacer; } public function getRuleDefinition() : RuleDefinition { return new RuleDefinition('Streamline the operator arguments of version_compare function', [new ConfiguredCodeSample(<<<'CODE_SAMPLE' version_compare(PHP_VERSION, '5.6', 'gte'); CODE_SAMPLE , <<<'CODE_SAMPLE' version_compare(PHP_VERSION, '5.6', 'ge'); CODE_SAMPLE , [new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'gte', 'ge')])]); } /** * @return array<class-string<Node>> */ public function getNodeTypes() : array { return [FuncCall::class]; } /** * @param FuncCall $node */ public function refactor(Node $node) : ?\PhpParser\Node\Expr\FuncCall { $hasChanged = \false; foreach ($this->replacedArguments as $replacedArgument) { if (!$this->isName($node->name, $replacedArgument->getFunction())) { continue; } $changedNode = $this->argumentDefaultValueReplacer->processReplaces($node, $replacedArgument); if ($changedNode instanceof Node) { $hasChanged = \true; } } if ($hasChanged) { return $node; } return null; } /** * @param mixed[] $configuration */ public function configure(array $configuration) : void { Assert::allIsAOf($configuration, ReplaceFuncCallArgumentDefaultValue::class); $this->replacedArguments = $configuration; } } ArgumentDefaultValueReplacer.php 0000644 00000015447 15126475523 0013044 0 ustar 00 <?php declare (strict_types=1); namespace Rector\Arguments; use PhpParser\BuilderHelpers; use PhpParser\Node\Arg; use PhpParser\Node\Expr; use PhpParser\Node\Expr\ClassConstFetch; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\New_; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Stmt\ClassMethod; use Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface; use Rector\Arguments\ValueObject\ReplaceArgumentDefaultValue; use Rector\PhpParser\Node\NodeFactory; use Rector\PhpParser\Node\Value\ValueResolver; final class ArgumentDefaultValueReplacer { /** * @readonly * @var \Rector\PhpParser\Node\NodeFactory */ private $nodeFactory; /** * @readonly * @var \Rector\PhpParser\Node\Value\ValueResolver */ private $valueResolver; public function __construct(NodeFactory $nodeFactory, ValueResolver $valueResolver) { $this->nodeFactory = $nodeFactory; $this->valueResolver = $valueResolver; } /** * @template TCall as (MethodCall|StaticCall|ClassMethod|FuncCall|New_) * * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\New_ $node * @return TCall|null */ public function processReplaces($node, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) { if ($node instanceof ClassMethod) { if (!isset($node->params[$replaceArgumentDefaultValue->getPosition()])) { return null; } return $this->processParams($node, $replaceArgumentDefaultValue); } if (!isset($node->args[$replaceArgumentDefaultValue->getPosition()])) { return null; } return $this->processArgs($node, $replaceArgumentDefaultValue); } /** * @param mixed $value */ private function isDefaultValueMatched(?Expr $expr, $value) : bool { // allow any values before, also allow param without default value if ($value === ReplaceArgumentDefaultValue::ANY_VALUE_BEFORE) { return \true; } if (!$expr instanceof Expr) { return \false; } if ($this->valueResolver->isValue($expr, $value)) { return \true; } // ValueResolver::isValue returns false when default value is `null` return $value === null && $this->valueResolver->isNull($expr); } private function processParams(ClassMethod $classMethod, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) : ?ClassMethod { $position = $replaceArgumentDefaultValue->getPosition(); if (!$this->isDefaultValueMatched($classMethod->params[$position]->default, $replaceArgumentDefaultValue->getValueBefore())) { return null; } $classMethod->params[$position]->default = $this->normalizeValue($replaceArgumentDefaultValue->getValueAfter()); return $classMethod; } /** * @template TCall as (MethodCall|StaticCall|FuncCall|New_) * * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\New_ $expr * @return TCall|null */ private function processArgs($expr, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) : ?Expr { if ($expr->isFirstClassCallable()) { return null; } $position = $replaceArgumentDefaultValue->getPosition(); $particularArg = $expr->getArgs()[$position] ?? null; if (!$particularArg instanceof Arg) { return null; } $argValue = $this->valueResolver->getValue($particularArg->value); if (\is_scalar($replaceArgumentDefaultValue->getValueBefore()) && $argValue === $replaceArgumentDefaultValue->getValueBefore()) { $expr->args[$position] = $this->normalizeValueToArgument($replaceArgumentDefaultValue->getValueAfter()); } elseif (\is_array($replaceArgumentDefaultValue->getValueBefore())) { $newArgs = $this->processArrayReplacement($expr->getArgs(), $replaceArgumentDefaultValue); if (\is_array($newArgs)) { $expr->args = $newArgs; } } return $expr; } /** * @param mixed $value */ private function normalizeValueToArgument($value) : Arg { return new Arg($this->normalizeValue($value)); } /** * @return \PhpParser\Node\Expr\ClassConstFetch|\PhpParser\Node\Expr * @param mixed $value */ private function normalizeValue($value) { // class constants → turn string to composite if (\is_string($value) && \strpos($value, '::') !== \false) { [$class, $constant] = \explode('::', $value); return $this->nodeFactory->createClassConstFetch($class, $constant); } return BuilderHelpers::normalizeValue($value); } /** * @param array<int, Arg> $args * @return array<int, Arg>|null */ private function processArrayReplacement(array $args, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) : ?array { $argumentValues = $this->resolveArgumentValuesToBeforeRecipe($args, $replaceArgumentDefaultValue); if ($argumentValues !== $replaceArgumentDefaultValue->getValueBefore()) { return null; } if (\is_string($replaceArgumentDefaultValue->getValueAfter())) { $args[$replaceArgumentDefaultValue->getPosition()] = $this->normalizeValueToArgument($replaceArgumentDefaultValue->getValueAfter()); // clear following arguments $argumentCountToClear = \count($replaceArgumentDefaultValue->getValueBefore()); for ($i = $replaceArgumentDefaultValue->getPosition() + 1; $i <= $replaceArgumentDefaultValue->getPosition() + $argumentCountToClear; ++$i) { unset($args[$i]); } } return $args; } /** * @param Arg[] $argumentNodes * @return mixed[] */ private function resolveArgumentValuesToBeforeRecipe(array $argumentNodes, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) : array { $argumentValues = []; $valueBefore = $replaceArgumentDefaultValue->getValueBefore(); if (!\is_array($valueBefore)) { return []; } $beforeArgumentCount = \count($valueBefore); for ($i = 0; $i < $beforeArgumentCount; ++$i) { if (!isset($argumentNodes[$replaceArgumentDefaultValue->getPosition() + $i])) { continue; } $nextArg = $argumentNodes[$replaceArgumentDefaultValue->getPosition() + $i]; $argumentValues[] = $this->valueResolver->getValue($nextArg->value); } return $argumentValues; } }
| ver. 1.6 |
Github
|
.
| PHP 8.2.30 | ??????????? ?????????: 0 |
proxy
|
phpinfo
|
???????????