mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-18 05:48:21 +01:00
[Nette] Remove AbstractWithFunctionToNetteUtilsStringsRector (#5742)
Co-authored-by: kaizen-ci <info@kaizen-ci.org>
This commit is contained in:
parent
abdc91606d
commit
92f2c5b3a6
@ -392,6 +392,15 @@ final class NodeNameResolver
|
||||
return $this->classNaming->getShortName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $renameMap
|
||||
*/
|
||||
public function matchNameFromMap(Node $node, array $renameMap): ?string
|
||||
{
|
||||
$name = $this->getName($node);
|
||||
return $renameMap[$name] ?? null;
|
||||
}
|
||||
|
||||
private function isCallOrIdentifier(Node $node): bool
|
||||
{
|
||||
return StaticInstanceOf::isOneOf($node, [MethodCall::class, StaticCall::class, Identifier::class]);
|
||||
|
@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Nette\Contract;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use Rector\Nette\ValueObject\ContentExprAndNeedleExpr;
|
||||
|
||||
interface WithFunctionToNetteUtilsStringsRectorInterface
|
||||
{
|
||||
public function getMethodName(): string;
|
||||
|
||||
public function matchContentAndNeedleOfSubstrOfVariableLength(
|
||||
Node $node,
|
||||
Variable $variable
|
||||
): ?ContentExprAndNeedleExpr;
|
||||
}
|
39
rules/nette/src/NodeAnalyzer/PregMatchAllAnalyzer.php
Normal file
39
rules/nette/src/NodeAnalyzer/PregMatchAllAnalyzer.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Nette\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\BinaryOp\Minus;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
|
||||
final class PregMatchAllAnalyzer
|
||||
{
|
||||
/**
|
||||
* Compensate enforced flag https://github.com/nette/utils/blob/e3dd1853f56ee9a68bfbb2e011691283c2ed420d/src/Utils/Strings.php#L487
|
||||
* See https://stackoverflow.com/a/61424319/1348344
|
||||
*
|
||||
* @param Arg[] $args
|
||||
* @return Arg[]
|
||||
*/
|
||||
public function compensateEnforcedFlag(string $methodName, FuncCall $funcCall, array $args): array
|
||||
{
|
||||
if ($methodName !== 'matchAll') {
|
||||
return $args;
|
||||
}
|
||||
|
||||
if (count($funcCall->args) !== 3) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
$constFetch = new ConstFetch(new Name('PREG_SET_ORDER'));
|
||||
$minus = new Minus($constFetch, new LNumber(1));
|
||||
$args[] = new Arg($minus);
|
||||
|
||||
return $args;
|
||||
}
|
||||
}
|
79
rules/nette/src/NodeAnalyzer/StrlenEndsWithResolver.php
Normal file
79
rules/nette/src/NodeAnalyzer/StrlenEndsWithResolver.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Nette\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\BinaryOp;
|
||||
use PhpParser\Node\Expr\BinaryOp\Identical;
|
||||
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\UnaryMinus;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use Rector\Core\PhpParser\Comparing\NodeComparator;
|
||||
use Rector\Nette\ValueObject\ContentExprAndNeedleExpr;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
|
||||
final class StrlenEndsWithResolver
|
||||
{
|
||||
/**
|
||||
* @var NodeNameResolver
|
||||
*/
|
||||
private $nodeNameResolver;
|
||||
|
||||
/**
|
||||
* @var NodeComparator
|
||||
*/
|
||||
private $nodeComparator;
|
||||
|
||||
public function __construct(NodeNameResolver $nodeNameResolver, NodeComparator $nodeComparator)
|
||||
{
|
||||
$this->nodeNameResolver = $nodeNameResolver;
|
||||
$this->nodeComparator = $nodeComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Identical|NotIdentical $binaryOp
|
||||
*/
|
||||
public function resolveBinaryOpForFunction(BinaryOp $binaryOp): ?ContentExprAndNeedleExpr
|
||||
{
|
||||
if ($binaryOp->left instanceof Variable) {
|
||||
return $this->matchContentExprAndNeedleExpr($binaryOp->right, $binaryOp->left);
|
||||
}
|
||||
|
||||
if ($binaryOp->right instanceof Variable) {
|
||||
return $this->matchContentExprAndNeedleExpr($binaryOp->left, $binaryOp->right);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function matchContentExprAndNeedleExpr(Node $node, Variable $variable): ?ContentExprAndNeedleExpr
|
||||
{
|
||||
if (! $this->nodeNameResolver->isFuncCallName($node, 'substr')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var FuncCall $node */
|
||||
if (! $node->args[1]->value instanceof UnaryMinus) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var UnaryMinus $unaryMinus */
|
||||
$unaryMinus = $node->args[1]->value;
|
||||
|
||||
if (! $this->nodeNameResolver->isFuncCallName($unaryMinus->expr, 'strlen')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var FuncCall $strlenFuncCall */
|
||||
$strlenFuncCall = $unaryMinus->expr;
|
||||
|
||||
if ($this->nodeComparator->areNodesEqual($strlenFuncCall->args[0]->value, $variable)) {
|
||||
return new ContentExprAndNeedleExpr($node->args[0]->value, $strlenFuncCall->args[0]->value);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
97
rules/nette/src/NodeAnalyzer/StrlenStartsWithResolver.php
Normal file
97
rules/nette/src/NodeAnalyzer/StrlenStartsWithResolver.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Nette\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\BinaryOp;
|
||||
use PhpParser\Node\Expr\BinaryOp\Identical;
|
||||
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use Rector\Core\PhpParser\Comparing\NodeComparator;
|
||||
use Rector\Core\PhpParser\Node\Value\ValueResolver;
|
||||
use Rector\Nette\ValueObject\ContentExprAndNeedleExpr;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
|
||||
final class StrlenStartsWithResolver
|
||||
{
|
||||
/**
|
||||
* @var NodeNameResolver
|
||||
*/
|
||||
private $nodeNameResolver;
|
||||
|
||||
/**
|
||||
* @var ValueResolver
|
||||
*/
|
||||
private $valueResolver;
|
||||
|
||||
/**
|
||||
* @var NodeComparator
|
||||
*/
|
||||
private $nodeComparator;
|
||||
|
||||
public function __construct(
|
||||
NodeNameResolver $nodeNameResolver,
|
||||
ValueResolver $valueResolver,
|
||||
NodeComparator $nodeComparator
|
||||
) {
|
||||
$this->nodeNameResolver = $nodeNameResolver;
|
||||
$this->valueResolver = $valueResolver;
|
||||
$this->nodeComparator = $nodeComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Identical|NotIdentical $binaryOp
|
||||
*/
|
||||
public function resolveBinaryOpForFunction(BinaryOp $binaryOp, string $functionName): ?ContentExprAndNeedleExpr
|
||||
{
|
||||
if ($binaryOp->left instanceof Variable) {
|
||||
return $this->matchContentExprAndNeedleExpr($binaryOp->right, $binaryOp->left, $functionName);
|
||||
}
|
||||
|
||||
if ($binaryOp->right instanceof Variable) {
|
||||
return $this->matchContentExprAndNeedleExpr($binaryOp->left, $binaryOp->right, $functionName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function matchContentExprAndNeedleExpr(
|
||||
Node $node, Variable $variable, string $functionName
|
||||
): ?ContentExprAndNeedleExpr {
|
||||
if (! $node instanceof FuncCall) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->nodeNameResolver->isName($node, $functionName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var FuncCall $node */
|
||||
if (! $this->valueResolver->isValue($node->args[1]->value, 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! isset($node->args[2])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $node->args[2]->value instanceof FuncCall) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->nodeNameResolver->isName($node->args[2]->value, 'strlen')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var FuncCall $strlenFuncCall */
|
||||
$strlenFuncCall = $node->args[2]->value;
|
||||
if ($this->nodeComparator->areNodesEqual($strlenFuncCall->args[0]->value, $variable)) {
|
||||
return new ContentExprAndNeedleExpr($node->args[0]->value, $strlenFuncCall->args[0]->value);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Nette\Rector\FuncCall;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\BinaryOp\Identical;
|
||||
use PhpParser\Node\Expr\Cast\Bool_;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Nette\Contract\PregToNetteUtilsStringInterface;
|
||||
|
||||
/**
|
||||
* @see https://tomasvotruba.com/blog/2019/02/07/what-i-learned-by-using-thecodingmachine-safe/#is-there-a-better-way
|
||||
*
|
||||
* @see \Rector\Nette\Tests\Rector\FuncCall\PregMatchFunctionToNetteUtilsStringsRector\PregMatchFunctionToNetteUtilsStringsRectorTest
|
||||
*/
|
||||
abstract class AbstractPregToNetteUtilsStringsRector extends AbstractRector implements PregToNetteUtilsStringInterface
|
||||
{
|
||||
/**
|
||||
* @param FuncCall|Identical $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($node instanceof Identical) {
|
||||
return $this->refactorIdentical($node);
|
||||
}
|
||||
|
||||
return $this->refactorFuncCall($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [FuncCall::class, Identical::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $functionRenameMap
|
||||
*/
|
||||
protected function matchFuncCallRenameToMethod(FuncCall $funcCall, array $functionRenameMap): ?string
|
||||
{
|
||||
$oldFunctionNames = array_keys($functionRenameMap);
|
||||
if (! $this->isNames($funcCall, $oldFunctionNames)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$currentFunctionName = $this->getName($funcCall);
|
||||
return $functionRenameMap[$currentFunctionName];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Expr $expr
|
||||
*/
|
||||
protected function createBoolCast(?Node $node, Node $expr): Bool_
|
||||
{
|
||||
if ($node instanceof Return_ && $expr instanceof Assign) {
|
||||
$expr = $expr->expr;
|
||||
}
|
||||
|
||||
return new Bool_($expr);
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace Rector\Nette\Rector\FuncCall;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
@ -17,6 +18,8 @@ use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
@ -26,7 +29,7 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
*
|
||||
* @see \Rector\Nette\Tests\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector\PregFunctionToNetteUtilsStringsRectorTest
|
||||
*/
|
||||
final class PregFunctionToNetteUtilsStringsRector extends AbstractPregToNetteUtilsStringsRector
|
||||
final class PregFunctionToNetteUtilsStringsRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var array<string, string>
|
||||
@ -76,6 +79,26 @@ CODE_SAMPLE
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FuncCall|Identical $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($node instanceof Identical) {
|
||||
return $this->refactorIdentical($node);
|
||||
}
|
||||
|
||||
return $this->refactorFuncCall($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [FuncCall::class, Identical::class];
|
||||
}
|
||||
|
||||
public function refactorIdentical(Identical $identical): ?Bool_
|
||||
{
|
||||
$parentNode = $identical->getAttribute(AttributeKey::PARENT_NODE);
|
||||
@ -102,7 +125,7 @@ CODE_SAMPLE
|
||||
*/
|
||||
public function refactorFuncCall(FuncCall $funcCall): ?Expr
|
||||
{
|
||||
$methodName = $this->matchFuncCallRenameToMethod($funcCall, self::FUNCTION_NAME_TO_METHOD_NAME);
|
||||
$methodName = $this->nodeNameResolver->matchNameFromMap($funcCall, self::FUNCTION_NAME_TO_METHOD_NAME);
|
||||
if ($methodName === null) {
|
||||
return null;
|
||||
}
|
||||
@ -134,6 +157,18 @@ CODE_SAMPLE
|
||||
return $matchStaticCall;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Expr $expr
|
||||
*/
|
||||
private function createBoolCast(?Node $node, Node $expr): Bool_
|
||||
{
|
||||
if ($node instanceof Return_ && $expr instanceof Assign) {
|
||||
$expr = $expr->expr;
|
||||
}
|
||||
|
||||
return new Bool_($expr);
|
||||
}
|
||||
|
||||
private function createMatchStaticCall(FuncCall $funcCall, string $methodName): StaticCall
|
||||
{
|
||||
$args = [];
|
||||
|
@ -4,18 +4,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace Rector\Nette\Rector\FuncCall;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\BinaryOp\Identical;
|
||||
use PhpParser\Node\Expr\BinaryOp\Minus;
|
||||
use PhpParser\Node\Expr\Cast\Bool_;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Nette\NodeAnalyzer\PregMatchAllAnalyzer;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
@ -25,7 +25,7 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
*
|
||||
* @see \Rector\Nette\Tests\Rector\FuncCall\PregMatchFunctionToNetteUtilsStringsRector\PregMatchFunctionToNetteUtilsStringsRectorTest
|
||||
*/
|
||||
final class PregMatchFunctionToNetteUtilsStringsRector extends AbstractPregToNetteUtilsStringsRector
|
||||
final class PregMatchFunctionToNetteUtilsStringsRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var array<string, string>
|
||||
@ -35,6 +35,16 @@ final class PregMatchFunctionToNetteUtilsStringsRector extends AbstractPregToNet
|
||||
'preg_match_all' => 'matchAll',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var PregMatchAllAnalyzer
|
||||
*/
|
||||
private $pregMatchAllAnalyzer;
|
||||
|
||||
public function __construct(PregMatchAllAnalyzer $pregMatchAllAnalyzer)
|
||||
{
|
||||
$this->pregMatchAllAnalyzer = $pregMatchAllAnalyzer;
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition(
|
||||
@ -68,6 +78,26 @@ CODE_SAMPLE
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FuncCall|Identical $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($node instanceof Identical) {
|
||||
return $this->refactorIdentical($node);
|
||||
}
|
||||
|
||||
return $this->refactorFuncCall($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [FuncCall::class, Identical::class];
|
||||
}
|
||||
|
||||
public function refactorIdentical(Identical $identical): ?Bool_
|
||||
{
|
||||
$parentNode = $identical->getAttribute(AttributeKey::PARENT_NODE);
|
||||
@ -94,7 +124,7 @@ CODE_SAMPLE
|
||||
*/
|
||||
public function refactorFuncCall(FuncCall $funcCall): ?Expr
|
||||
{
|
||||
$methodName = $this->matchFuncCallRenameToMethod($funcCall, self::FUNCTION_NAME_TO_METHOD_NAME);
|
||||
$methodName = $this->nodeNameResolver->matchNameFromMap($funcCall, self::FUNCTION_NAME_TO_METHOD_NAME);
|
||||
if ($methodName === null) {
|
||||
return null;
|
||||
}
|
||||
@ -120,38 +150,25 @@ CODE_SAMPLE
|
||||
return $matchStaticCall;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Expr $expr
|
||||
*/
|
||||
private function createBoolCast(?Node $node, Node $expr): Bool_
|
||||
{
|
||||
if ($node instanceof Return_ && $expr instanceof Assign) {
|
||||
$expr = $expr->expr;
|
||||
}
|
||||
|
||||
return new Bool_($expr);
|
||||
}
|
||||
|
||||
private function createMatchStaticCall(FuncCall $funcCall, string $methodName): StaticCall
|
||||
{
|
||||
$args = [];
|
||||
$args[] = $funcCall->args[1];
|
||||
$args[] = $funcCall->args[0];
|
||||
|
||||
$args = $this->compensateMatchAllEnforcedFlag($methodName, $funcCall, $args);
|
||||
|
||||
$args = $this->pregMatchAllAnalyzer->compensateEnforcedFlag($methodName, $funcCall, $args);
|
||||
return $this->nodeFactory->createStaticCall('Nette\Utils\Strings', $methodName, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compensate enforced flag https://github.com/nette/utils/blob/e3dd1853f56ee9a68bfbb2e011691283c2ed420d/src/Utils/Strings.php#L487
|
||||
* See https://stackoverflow.com/a/61424319/1348344
|
||||
*
|
||||
* @param Arg[] $args
|
||||
* @return Arg[]
|
||||
*/
|
||||
private function compensateMatchAllEnforcedFlag(string $methodName, FuncCall $funcCall, array $args): array
|
||||
{
|
||||
if ($methodName !== 'matchAll') {
|
||||
return $args;
|
||||
}
|
||||
|
||||
if (count($funcCall->args) !== 3) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
$constFetch = new ConstFetch(new Name('PREG_SET_ORDER'));
|
||||
$minus = new Minus($constFetch, new LNumber(1));
|
||||
$args[] = new Arg($minus);
|
||||
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
|
@ -1,64 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Nette\Rector\Identical;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\BinaryOp;
|
||||
use PhpParser\Node\Expr\BinaryOp\Identical;
|
||||
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
|
||||
use PhpParser\Node\Expr\BooleanNot;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Nette\Contract\WithFunctionToNetteUtilsStringsRectorInterface;
|
||||
use Rector\Nette\ValueObject\ContentExprAndNeedleExpr;
|
||||
|
||||
abstract class AbstractWithFunctionToNetteUtilsStringsRector extends AbstractRector implements WithFunctionToNetteUtilsStringsRectorInterface
|
||||
{
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Identical::class, NotIdentical::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Identical|NotIdentical $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
$contentExprAndNeedleExpr = $this->resolveContentExprAndNeedleExpr($node);
|
||||
if (! $contentExprAndNeedleExpr instanceof ContentExprAndNeedleExpr) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$staticCall = $this->nodeFactory->createStaticCall('Nette\Utils\Strings', $this->getMethodName(), [
|
||||
$contentExprAndNeedleExpr->getContentExpr(),
|
||||
$contentExprAndNeedleExpr->getNeedleExpr(),
|
||||
]);
|
||||
|
||||
if ($node instanceof NotIdentical) {
|
||||
return new BooleanNot($staticCall);
|
||||
}
|
||||
|
||||
return $staticCall;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Identical|NotIdentical $binaryOp
|
||||
*/
|
||||
private function resolveContentExprAndNeedleExpr(BinaryOp $binaryOp): ?ContentExprAndNeedleExpr
|
||||
{
|
||||
if ($binaryOp->left instanceof Variable) {
|
||||
return $this->matchContentAndNeedleOfSubstrOfVariableLength($binaryOp->right, $binaryOp->left);
|
||||
}
|
||||
|
||||
if ($binaryOp->right instanceof Variable) {
|
||||
return $this->matchContentAndNeedleOfSubstrOfVariableLength($binaryOp->left, $binaryOp->right);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -5,9 +5,11 @@ declare(strict_types=1);
|
||||
namespace Rector\Nette\Rector\Identical;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\UnaryMinus;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Expr\BinaryOp\Identical;
|
||||
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
|
||||
use PhpParser\Node\Expr\BooleanNot;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Nette\NodeAnalyzer\StrlenEndsWithResolver;
|
||||
use Rector\Nette\ValueObject\ContentExprAndNeedleExpr;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
@ -16,8 +18,26 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
* @see https://github.com/nette/utils/blob/master/src/Utils/Strings.php
|
||||
* @see \Rector\Nette\Tests\Rector\Identical\EndsWithFunctionToNetteUtilsStringsRector\EndsWithFunctionToNetteUtilsStringsRectorTest
|
||||
*/
|
||||
final class EndsWithFunctionToNetteUtilsStringsRector extends AbstractWithFunctionToNetteUtilsStringsRector
|
||||
final class EndsWithFunctionToNetteUtilsStringsRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var StrlenEndsWithResolver
|
||||
*/
|
||||
private $strlenEndsWithResolver;
|
||||
|
||||
public function __construct(StrlenEndsWithResolver $strlenEndsWithResolver)
|
||||
{
|
||||
$this->strlenEndsWithResolver = $strlenEndsWithResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Identical::class, NotIdentical::class];
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition(
|
||||
@ -37,13 +57,14 @@ class SomeClass
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
use Nette\Utils\Strings;
|
||||
|
||||
class SomeClass
|
||||
{
|
||||
public function end($needle)
|
||||
{
|
||||
$content = 'Hi, my name is Tom';
|
||||
|
||||
$yes = \Nette\Utils\Strings::endsWith($content, $needle);
|
||||
$yes = Strings::endsWith($content, $needle);
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
@ -51,38 +72,25 @@ CODE_SAMPLE
|
||||
]);
|
||||
}
|
||||
|
||||
public function getMethodName(): string
|
||||
/**
|
||||
* @param Identical|NotIdentical $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
return 'endsWith';
|
||||
}
|
||||
|
||||
public function matchContentAndNeedleOfSubstrOfVariableLength(
|
||||
Node $node,
|
||||
Variable $variable
|
||||
): ?ContentExprAndNeedleExpr {
|
||||
if (! $this->nodeNameResolver->isFuncCallName($node, 'substr')) {
|
||||
$contentExprAndNeedleExpr = $this->strlenEndsWithResolver->resolveBinaryOpForFunction($node);
|
||||
if (! $contentExprAndNeedleExpr instanceof ContentExprAndNeedleExpr) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var FuncCall $node */
|
||||
if (! $node->args[1]->value instanceof UnaryMinus) {
|
||||
return null;
|
||||
$staticCall = $this->nodeFactory->createStaticCall('Nette\Utils\Strings', 'endsWith', [
|
||||
$contentExprAndNeedleExpr->getContentExpr(),
|
||||
$contentExprAndNeedleExpr->getNeedleExpr(),
|
||||
]);
|
||||
|
||||
if ($node instanceof NotIdentical) {
|
||||
return new BooleanNot($staticCall);
|
||||
}
|
||||
|
||||
/** @var UnaryMinus $unaryMinus */
|
||||
$unaryMinus = $node->args[1]->value;
|
||||
|
||||
if (! $this->nodeNameResolver->isFuncCallName($unaryMinus->expr, 'strlen')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var FuncCall $strlenFuncCall */
|
||||
$strlenFuncCall = $unaryMinus->expr;
|
||||
|
||||
if ($this->nodeComparator->areNodesEqual($strlenFuncCall->args[0]->value, $variable)) {
|
||||
return new ContentExprAndNeedleExpr($node->args[0]->value, $strlenFuncCall->args[0]->value);
|
||||
}
|
||||
|
||||
return null;
|
||||
return $staticCall;
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,11 @@ declare(strict_types=1);
|
||||
namespace Rector\Nette\Rector\Identical;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Expr\BinaryOp\Identical;
|
||||
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
|
||||
use PhpParser\Node\Expr\BooleanNot;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Nette\NodeAnalyzer\StrlenStartsWithResolver;
|
||||
use Rector\Nette\ValueObject\ContentExprAndNeedleExpr;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
@ -16,77 +19,77 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
*
|
||||
* @see \Rector\Nette\Tests\Rector\Identical\StartsWithFunctionToNetteUtilsStringsRector\StartsWithFunctionToNetteUtilsStringsRectorTest
|
||||
*/
|
||||
final class StartsWithFunctionToNetteUtilsStringsRector extends AbstractWithFunctionToNetteUtilsStringsRector
|
||||
final class StartsWithFunctionToNetteUtilsStringsRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var StrlenStartsWithResolver
|
||||
*/
|
||||
private $strlenStartsWithResolver;
|
||||
|
||||
public function __construct(StrlenStartsWithResolver $strlenStartsWithResolver)
|
||||
{
|
||||
$this->strlenStartsWithResolver = $strlenStartsWithResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Identical::class, NotIdentical::class];
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition(
|
||||
'Use Nette\Utils\Strings::startsWith() over bare string-functions',
|
||||
[
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
return new RuleDefinition('Use Nette\Utils\Strings::startsWith() over bare string-functions', [
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass
|
||||
{
|
||||
public function start($needle)
|
||||
{
|
||||
$content = 'Hi, my name is Tom';
|
||||
|
||||
$yes = substr($content, 0, strlen($needle)) === $needle;
|
||||
}
|
||||
public function start($needle)
|
||||
{
|
||||
$content = 'Hi, my name is Tom';
|
||||
$yes = substr($content, 0, strlen($needle)) === $needle;
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
use Nette\Utils\Strings;
|
||||
|
||||
class SomeClass
|
||||
{
|
||||
public function start($needle)
|
||||
{
|
||||
$content = 'Hi, my name is Tom';
|
||||
|
||||
$yes = \Nette\Utils\Strings::startsWith($content, $needle);
|
||||
}
|
||||
public function start($needle)
|
||||
{
|
||||
$content = 'Hi, my name is Tom';
|
||||
$yes = Strings::startsWith($content, $needle);
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
),
|
||||
]);
|
||||
]);
|
||||
}
|
||||
|
||||
public function getMethodName(): string
|
||||
/**
|
||||
* @param Identical|NotIdentical $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
return 'startsWith';
|
||||
}
|
||||
$contentExprAndNeedleExpr = $this->strlenStartsWithResolver->resolveBinaryOpForFunction($node, 'substr');
|
||||
|
||||
public function matchContentAndNeedleOfSubstrOfVariableLength(
|
||||
Node $node,
|
||||
Variable $variable
|
||||
): ?ContentExprAndNeedleExpr {
|
||||
if (! $this->nodeNameResolver->isFuncCallName($node, 'substr')) {
|
||||
if (! $contentExprAndNeedleExpr instanceof ContentExprAndNeedleExpr) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var FuncCall $node */
|
||||
if (! $this->valueResolver->isValue($node->args[1]->value, 0)) {
|
||||
return null;
|
||||
$staticCall = $this->nodeFactory->createStaticCall('Nette\Utils\Strings', 'startsWith', [
|
||||
$contentExprAndNeedleExpr->getContentExpr(),
|
||||
$contentExprAndNeedleExpr->getNeedleExpr(),
|
||||
]);
|
||||
|
||||
if ($node instanceof NotIdentical) {
|
||||
return new BooleanNot($staticCall);
|
||||
}
|
||||
|
||||
if (! isset($node->args[2])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $node->args[2]->value instanceof FuncCall) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->isName($node->args[2]->value, 'strlen')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var FuncCall $strlenFuncCall */
|
||||
$strlenFuncCall = $node->args[2]->value;
|
||||
if ($this->nodeComparator->areNodesEqual($strlenFuncCall->args[0]->value, $variable)) {
|
||||
return new ContentExprAndNeedleExpr($node->args[0]->value, $strlenFuncCall->args[0]->value);
|
||||
}
|
||||
|
||||
return null;
|
||||
return $staticCall;
|
||||
}
|
||||
}
|
||||
|
@ -40,9 +40,9 @@ final class AnonymousFunctionFactory
|
||||
/**
|
||||
* @param Param[] $params
|
||||
* @param Stmt[] $stmts
|
||||
* @param Identifier|Name|NullableType|UnionType|null $node
|
||||
* @param Identifier|Name|NullableType|UnionType|null $returnTypeNode
|
||||
*/
|
||||
public function create(array $params, array $stmts, ?Node $node): Closure
|
||||
public function create(array $params, array $stmts, ?Node $returnTypeNode): Closure
|
||||
{
|
||||
$useVariables = $this->createUseVariablesFromParams($stmts, $params);
|
||||
|
||||
@ -53,8 +53,8 @@ final class AnonymousFunctionFactory
|
||||
$anonymousFunctionNode->uses[] = new ClosureUse($useVariable);
|
||||
}
|
||||
|
||||
if ($node instanceof Node) {
|
||||
$anonymousFunctionNode->returnType = $node;
|
||||
if ($returnTypeNode instanceof Node) {
|
||||
$anonymousFunctionNode->returnType = $returnTypeNode;
|
||||
}
|
||||
|
||||
$anonymousFunctionNode->stmts = $stmts;
|
||||
|
@ -6,7 +6,6 @@ namespace Rector\Privatization\Rector\ClassMethod;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PHPStan\Type\ObjectType;
|
||||
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||
namespace Rector\Privatization\Tests\Rector\ClassMethod\PrivatizeLocalOnlyMethodRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Privatization\Rector\ClassMethod\PrivatizeLocalOnlyMethodRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
|
@ -19,8 +19,6 @@ services:
|
||||
- Rector\Core\Rector\AbstractTemporaryRector
|
||||
- Rector\PhpSpecToPHPUnit\Rector\AbstractPhpSpecToPHPUnitRector
|
||||
# solve later
|
||||
- Rector\Nette\Rector\FuncCall\AbstractPregToNetteUtilsStringsRector
|
||||
- Rector\Nette\Rector\Identical\AbstractWithFunctionToNetteUtilsStringsRector
|
||||
- Rector\TypeDeclaration\Rector\FunctionLike\AbstractTypeDeclarationRector
|
||||
- Rector\Symfony\Rector\MethodCall\AbstractToConstructorInjectionRector
|
||||
- Rector\NetteCodeQuality\Rector\ArrayDimFetch\AbstractArrayDimFetchToAnnotatedControlVariableRector
|
||||
|
Loading…
x
Reference in New Issue
Block a user