diff --git a/packages/node-name-resolver/src/NodeNameResolver.php b/packages/node-name-resolver/src/NodeNameResolver.php index d94339dd8dd..5f9869ba5e5 100644 --- a/packages/node-name-resolver/src/NodeNameResolver.php +++ b/packages/node-name-resolver/src/NodeNameResolver.php @@ -392,6 +392,15 @@ final class NodeNameResolver return $this->classNaming->getShortName($name); } + /** + * @param array $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]); diff --git a/rules/nette/src/Contract/WithFunctionToNetteUtilsStringsRectorInterface.php b/rules/nette/src/Contract/WithFunctionToNetteUtilsStringsRectorInterface.php deleted file mode 100644 index d3516dbf664..00000000000 --- a/rules/nette/src/Contract/WithFunctionToNetteUtilsStringsRectorInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -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; + } +} diff --git a/rules/nette/src/NodeAnalyzer/StrlenEndsWithResolver.php b/rules/nette/src/NodeAnalyzer/StrlenEndsWithResolver.php new file mode 100644 index 00000000000..faaa6346973 --- /dev/null +++ b/rules/nette/src/NodeAnalyzer/StrlenEndsWithResolver.php @@ -0,0 +1,79 @@ +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; + } +} diff --git a/rules/nette/src/NodeAnalyzer/StrlenStartsWithResolver.php b/rules/nette/src/NodeAnalyzer/StrlenStartsWithResolver.php new file mode 100644 index 00000000000..e0bbb47606d --- /dev/null +++ b/rules/nette/src/NodeAnalyzer/StrlenStartsWithResolver.php @@ -0,0 +1,97 @@ +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; + } +} diff --git a/rules/nette/src/Rector/FuncCall/AbstractPregToNetteUtilsStringsRector.php b/rules/nette/src/Rector/FuncCall/AbstractPregToNetteUtilsStringsRector.php deleted file mode 100644 index c92480ce950..00000000000 --- a/rules/nette/src/Rector/FuncCall/AbstractPregToNetteUtilsStringsRector.php +++ /dev/null @@ -1,69 +0,0 @@ -refactorIdentical($node); - } - - return $this->refactorFuncCall($node); - } - - /** - * @return array> - */ - public function getNodeTypes(): array - { - return [FuncCall::class, Identical::class]; - } - - /** - * @param array $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); - } -} diff --git a/rules/nette/src/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector.php b/rules/nette/src/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector.php index 735b2e098bb..ae9f9845db2 100644 --- a/rules/nette/src/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector.php +++ b/rules/nette/src/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector.php @@ -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 @@ -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> + */ + 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 = []; diff --git a/rules/nette/src/Rector/FuncCall/PregMatchFunctionToNetteUtilsStringsRector.php b/rules/nette/src/Rector/FuncCall/PregMatchFunctionToNetteUtilsStringsRector.php index bc17a95a92b..1a86a2ef272 100644 --- a/rules/nette/src/Rector/FuncCall/PregMatchFunctionToNetteUtilsStringsRector.php +++ b/rules/nette/src/Rector/FuncCall/PregMatchFunctionToNetteUtilsStringsRector.php @@ -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 @@ -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> + */ + 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; - } } diff --git a/rules/nette/src/Rector/Identical/AbstractWithFunctionToNetteUtilsStringsRector.php b/rules/nette/src/Rector/Identical/AbstractWithFunctionToNetteUtilsStringsRector.php deleted file mode 100644 index 9aa59b4a5d1..00000000000 --- a/rules/nette/src/Rector/Identical/AbstractWithFunctionToNetteUtilsStringsRector.php +++ /dev/null @@ -1,64 +0,0 @@ -> - */ - 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; - } -} diff --git a/rules/nette/src/Rector/Identical/EndsWithFunctionToNetteUtilsStringsRector.php b/rules/nette/src/Rector/Identical/EndsWithFunctionToNetteUtilsStringsRector.php index 80df2481585..e1cf1c551ca 100644 --- a/rules/nette/src/Rector/Identical/EndsWithFunctionToNetteUtilsStringsRector.php +++ b/rules/nette/src/Rector/Identical/EndsWithFunctionToNetteUtilsStringsRector.php @@ -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> + */ + 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; } } diff --git a/rules/nette/src/Rector/Identical/StartsWithFunctionToNetteUtilsStringsRector.php b/rules/nette/src/Rector/Identical/StartsWithFunctionToNetteUtilsStringsRector.php index 0a4b0bd4bf1..a50e3b9ecbc 100644 --- a/rules/nette/src/Rector/Identical/StartsWithFunctionToNetteUtilsStringsRector.php +++ b/rules/nette/src/Rector/Identical/StartsWithFunctionToNetteUtilsStringsRector.php @@ -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> + */ + 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; } } diff --git a/rules/php72/src/NodeFactory/AnonymousFunctionFactory.php b/rules/php72/src/NodeFactory/AnonymousFunctionFactory.php index cc2e787c900..d98c47369d8 100644 --- a/rules/php72/src/NodeFactory/AnonymousFunctionFactory.php +++ b/rules/php72/src/NodeFactory/AnonymousFunctionFactory.php @@ -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; diff --git a/rules/privatization/src/Rector/ClassMethod/PrivatizeLocalOnlyMethodRector.php b/rules/privatization/src/Rector/ClassMethod/PrivatizeLocalOnlyMethodRector.php index 96eefb608ef..65a45816dfc 100644 --- a/rules/privatization/src/Rector/ClassMethod/PrivatizeLocalOnlyMethodRector.php +++ b/rules/privatization/src/Rector/ClassMethod/PrivatizeLocalOnlyMethodRector.php @@ -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; diff --git a/rules/privatization/tests/Rector/ClassMethod/PrivatizeLocalOnlyMethodRector/Php8Test.php b/rules/privatization/tests/Rector/ClassMethod/PrivatizeLocalOnlyMethodRector/Php8Test.php index 849070e964e..33367016e28 100644 --- a/rules/privatization/tests/Rector/ClassMethod/PrivatizeLocalOnlyMethodRector/Php8Test.php +++ b/rules/privatization/tests/Rector/ClassMethod/PrivatizeLocalOnlyMethodRector/Php8Test.php @@ -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; diff --git a/utils/phpstan-extensions/config/rector-rules.neon b/utils/phpstan-extensions/config/rector-rules.neon index 340cb93eb6f..2c8c0a330dd 100644 --- a/utils/phpstan-extensions/config/rector-rules.neon +++ b/utils/phpstan-extensions/config/rector-rules.neon @@ -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