Skip to content

Commit 8b209cb

Browse files
committed
Deprecate WillReturnCallbackFallbackToThrowRector
The case is very rare and hardly automatable, and the rule is not part of any set - it sat commented out in the code-quality set. Better handle it in a custom way, or keep the code untouched.
1 parent e1bfd76 commit 8b209cb

7 files changed

Lines changed: 8 additions & 248 deletions

File tree

‎config/sets/phpunit-code-quality.php‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,6 @@
8989
NarrowSingleWillReturnCallbackRector::class,
9090
SingleWithConsecutiveToWithRector::class,
9191

92-
// enable once better tested
93-
// WillReturnCallbackFallbackToThrowRector::class,
94-
9592
// type declarations
9693
TypeWillReturnCallableArrowFunctionRector::class,
9794
VoidMethodWithCallbackToWillReturnCallbackRector::class,

‎rules-tests/CodeQuality/Rector/MethodCall/WillReturnCallbackFallbackToThrowRector/Fixture/skip_fallback_return.php.inc‎

Lines changed: 0 additions & 28 deletions
This file was deleted.

‎rules-tests/CodeQuality/Rector/MethodCall/WillReturnCallbackFallbackToThrowRector/Fixture/skip_no_matcher_branch.php.inc‎

Lines changed: 0 additions & 20 deletions
This file was deleted.

‎rules-tests/CodeQuality/Rector/MethodCall/WillReturnCallbackFallbackToThrowRector/Fixture/void_fallback.php.inc‎

Lines changed: 0 additions & 50 deletions
This file was deleted.

‎rules-tests/CodeQuality/Rector/MethodCall/WillReturnCallbackFallbackToThrowRector/WillReturnCallbackFallbackToThrowRectorTest.php‎

Lines changed: 0 additions & 28 deletions
This file was deleted.

‎rules-tests/CodeQuality/Rector/MethodCall/WillReturnCallbackFallbackToThrowRector/config/configured_rule.php‎

Lines changed: 0 additions & 10 deletions
This file was deleted.

‎rules/CodeQuality/Rector/MethodCall/WillReturnCallbackFallbackToThrowRector.php‎

Lines changed: 8 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,18 @@
55
namespace Rector\PHPUnit\CodeQuality\Rector\MethodCall;
66

77
use PhpParser\Node;
8-
use PhpParser\Node\Arg;
9-
use PhpParser\Node\ClosureUse;
10-
use PhpParser\Node\Expr\Closure;
118
use PhpParser\Node\Expr\MethodCall;
12-
use PhpParser\Node\Expr\New_;
13-
use PhpParser\Node\Expr\Throw_;
14-
use PhpParser\Node\Expr\Variable;
15-
use PhpParser\Node\Name\FullyQualified;
16-
use PhpParser\Node\Scalar\String_;
17-
use PhpParser\Node\Stmt\Expression;
18-
use PhpParser\Node\Stmt\If_;
19-
use Rector\PHPUnit\Enum\ConsecutiveVariable;
20-
use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer;
21-
use Rector\PHPUnit\NodeFactory\MatcherInvocationCountMethodCallNodeFactory;
9+
use Rector\Configuration\Deprecation\Contract\DeprecatedInterface;
10+
use Rector\Exception\ShouldNotHappenException;
2211
use Rector\Rector\AbstractRector;
2312
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
2413
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
2514

2615
/**
27-
* @see \Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\WillReturnCallbackFallbackToThrowRector\WillReturnCallbackFallbackToThrowRectorTest
16+
* @deprecated This rule is deprecated as the case is very rare, hardly automatable and it is not part of any set. Handle it in a custom way or keep the code untouched.
2817
*/
29-
final class WillReturnCallbackFallbackToThrowRector extends AbstractRector
18+
final class WillReturnCallbackFallbackToThrowRector extends AbstractRector implements DeprecatedInterface
3019
{
31-
public function __construct(
32-
private readonly TestsNodeAnalyzer $testsNodeAnalyzer,
33-
private readonly MatcherInvocationCountMethodCallNodeFactory $matcherInvocationCountMethodCallNodeFactory,
34-
) {
35-
}
36-
3720
public function getRuleDefinition(): RuleDefinition
3821
{
3922
return new RuleDefinition(
@@ -99,93 +82,9 @@ public function getNodeTypes(): array
9982
*/
10083
public function refactor(Node $node): ?MethodCall
10184
{
102-
if (! $this->testsNodeAnalyzer->isInTestClass($node)) {
103-
return null;
104-
}
105-
106-
if (! $this->isName($node->name, 'willReturnCallback')) {
107-
return null;
108-
}
109-
110-
if ($node->isFirstClassCallable()) {
111-
return null;
112-
}
113-
114-
if (count($node->getArgs()) !== 1) {
115-
return null;
116-
}
117-
118-
$closure = $node->getArgs()[0]
119-
->value;
120-
if (! $closure instanceof Closure) {
121-
return null;
122-
}
123-
124-
if (! $this->usesMatcher($closure)) {
125-
return null;
126-
}
127-
128-
// the closure must branch on the matcher invocation count first
129-
if (! $this->hasConsecutiveIf($closure)) {
130-
return null;
131-
}
132-
133-
$lastStmt = $closure->stmts[array_key_last($closure->stmts)] ?? null;
134-
135-
// the last statement must be an if branch; an explicit fallback "return <expr>;" is left untouched
136-
if (! $lastStmt instanceof If_) {
137-
return null;
138-
}
139-
140-
$closure->stmts[] = $this->createThrow();
141-
142-
return $node;
143-
}
144-
145-
private function usesMatcher(Closure $closure): bool
146-
{
147-
return array_any(
148-
$closure->uses,
149-
fn (ClosureUse $use): bool => $this->isName($use->var, ConsecutiveVariable::MATCHER)
150-
);
151-
}
152-
153-
private function hasConsecutiveIf(Closure $closure): bool
154-
{
155-
foreach ($closure->stmts as $stmt) {
156-
if (! $stmt instanceof If_) {
157-
continue;
158-
}
159-
160-
$hasMatcherCall = false;
161-
$this->traverseNodesWithCallable($stmt->cond, function (Node $node) use (&$hasMatcherCall): null {
162-
if ($node instanceof MethodCall
163-
&& $node->var instanceof Variable
164-
&& $this->isName($node->var, ConsecutiveVariable::MATCHER)
165-
) {
166-
$hasMatcherCall = true;
167-
}
168-
169-
return null;
170-
});
171-
172-
if ($hasMatcherCall) {
173-
return true;
174-
}
175-
}
176-
177-
return false;
178-
}
179-
180-
private function createThrow(): Expression
181-
{
182-
$sprintfFuncCall = $this->nodeFactory->createFuncCall('sprintf', [
183-
new String_('Method should not be called for the %dth time'),
184-
$this->matcherInvocationCountMethodCallNodeFactory->create(),
185-
]);
186-
187-
$new = new New_(new FullyQualified('PHPUnit\Framework\Exception'), [new Arg($sprintfFuncCall)]);
188-
189-
return new Expression(new Throw_($new));
85+
throw new ShouldNotHappenException(sprintf(
86+
'"%s" is deprecated and should not be used anymore. Remove it from your config files.',
87+
self::class,
88+
));
19089
}
19190
}

0 commit comments

Comments
 (0)