Skip to content

Commit 30c1e33

Browse files
committed
Updated Rector to commit 72f8056755dc28dd1a8ab8f39900259f129ebae8
rectorphp/rector-src@72f8056 [CodeQuality] Deprecate UnusedForeachValueToArrayKeysRector (#8278)
1 parent 8e262e1 commit 30c1e33

3 files changed

Lines changed: 8 additions & 133 deletions

File tree

rules/CodeQuality/Rector/Foreach_/UnusedForeachValueToArrayKeysRector.php

Lines changed: 5 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,17 @@
44
namespace Rector\CodeQuality\Rector\Foreach_;
55

66
use PhpParser\Node;
7-
use PhpParser\Node\ArrayItem;
8-
use PhpParser\Node\Expr;
9-
use PhpParser\Node\Expr\List_;
10-
use PhpParser\Node\Expr\Variable;
11-
use PhpParser\Node\Stmt\Foreach_;
12-
use Rector\DeadCode\NodeAnalyzer\ExprUsedInNodeAnalyzer;
13-
use Rector\NodeManipulator\StmtsManipulator;
7+
use Rector\Configuration\Deprecation\Contract\DeprecatedInterface;
8+
use Rector\Exception\ShouldNotHappenException;
149
use Rector\PhpParser\Enum\NodeGroup;
15-
use Rector\PhpParser\Node\BetterNodeFinder;
1610
use Rector\Rector\AbstractRector;
1711
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
1812
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
1913
/**
20-
* @see \Rector\Tests\CodeQuality\Rector\Foreach_\UnusedForeachValueToArrayKeysRector\UnusedForeachValueToArrayKeysRectorTest
14+
* @deprecated This rule is deprecated, as it is a personal preference. The array_keys() wrap makes the foreach harder to read and harder to extend, once the value is needed again.
2115
*/
22-
final class UnusedForeachValueToArrayKeysRector extends AbstractRector
16+
final class UnusedForeachValueToArrayKeysRector extends AbstractRector implements DeprecatedInterface
2317
{
24-
/**
25-
* @readonly
26-
*/
27-
private ExprUsedInNodeAnalyzer $exprUsedInNodeAnalyzer;
28-
/**
29-
* @readonly
30-
*/
31-
private BetterNodeFinder $betterNodeFinder;
32-
/**
33-
* @readonly
34-
*/
35-
private StmtsManipulator $stmtsManipulator;
36-
public function __construct(ExprUsedInNodeAnalyzer $exprUsedInNodeAnalyzer, BetterNodeFinder $betterNodeFinder, StmtsManipulator $stmtsManipulator)
37-
{
38-
$this->exprUsedInNodeAnalyzer = $exprUsedInNodeAnalyzer;
39-
$this->betterNodeFinder = $betterNodeFinder;
40-
$this->stmtsManipulator = $stmtsManipulator;
41-
}
4218
public function getRuleDefinition(): RuleDefinition
4319
{
4420
return new RuleDefinition('Change foreach with unused $value but only $key, to array_keys()', [new CodeSample(<<<'CODE_SAMPLE'
@@ -79,106 +55,6 @@ public function getNodeTypes(): array
7955
*/
8056
public function refactor(Node $node): ?Node
8157
{
82-
$stmts = $node->stmts;
83-
if ($stmts === null) {
84-
return null;
85-
}
86-
$hasChanged = \false;
87-
foreach ($stmts as $key => $stmt) {
88-
if (!$stmt instanceof Foreach_) {
89-
continue;
90-
}
91-
if (!$stmt->keyVar instanceof Expr) {
92-
continue;
93-
}
94-
if (!$this->nodeTypeResolver->getNativeType($stmt->expr)->isArray()->yes()) {
95-
continue;
96-
}
97-
// special case of nested array items
98-
if ($stmt->valueVar instanceof List_) {
99-
$valueArray = $this->refactorArrayForeachValue($stmt->valueVar, $stmt);
100-
if (!$valueArray instanceof List_) {
101-
continue;
102-
}
103-
$stmt->valueVar = $valueArray;
104-
// not sure what does this mean :)
105-
if ($valueArray->items !== []) {
106-
continue;
107-
}
108-
$hasChanged = \true;
109-
$this->removeForeachValueAndUseArrayKeys($stmt, $stmt->keyVar);
110-
continue;
111-
}
112-
if (!$stmt->valueVar instanceof Variable) {
113-
continue;
114-
}
115-
if ($this->isVariableUsedInForeach($stmt->valueVar, $stmt)) {
116-
continue;
117-
}
118-
if ($this->stmtsManipulator->isVariableUsedInNextStmt($node, $key + 1, (string) $this->getName($stmt->valueVar))) {
119-
continue;
120-
}
121-
$hasChanged = \true;
122-
$this->removeForeachValueAndUseArrayKeys($stmt, $stmt->keyVar);
123-
}
124-
if (!$hasChanged) {
125-
return null;
126-
}
127-
return $node;
128-
}
129-
/**
130-
* @param int[] $removedKeys
131-
*/
132-
private function isArrayItemsRemovalWithoutChangingOrder(List_ $list, array $removedKeys): bool
133-
{
134-
$hasRemovingStarted = \false;
135-
foreach (array_keys($list->items) as $key) {
136-
if (in_array($key, $removedKeys, \true)) {
137-
$hasRemovingStarted = \true;
138-
} elseif ($hasRemovingStarted) {
139-
// we cannot remove the previous item, and not remove the next one, because that would change the order
140-
return \false;
141-
}
142-
}
143-
return \true;
144-
}
145-
private function refactorArrayForeachValue(List_ $list, Foreach_ $foreach): ?List_
146-
{
147-
// only last items can be removed, without changing the order
148-
$removedKeys = [];
149-
foreach ($list->items as $key => $arrayItem) {
150-
if (!$arrayItem instanceof ArrayItem) {
151-
// only known values can be processes
152-
return null;
153-
}
154-
$value = $arrayItem->value;
155-
if (!$value instanceof Variable) {
156-
// only variables can be processed
157-
return null;
158-
}
159-
if ($this->isVariableUsedInForeach($value, $foreach)) {
160-
continue;
161-
}
162-
$removedKeys[] = $key;
163-
}
164-
if (!$this->isArrayItemsRemovalWithoutChangingOrder($list, $removedKeys)) {
165-
return null;
166-
}
167-
// clear removed items
168-
foreach ($removedKeys as $removedKey) {
169-
unset($list->items[$removedKey]);
170-
}
171-
return $list;
172-
}
173-
private function isVariableUsedInForeach(Variable $variable, Foreach_ $foreach): bool
174-
{
175-
return (bool) $this->betterNodeFinder->findFirst($foreach->stmts, fn(Node $node): bool => $this->exprUsedInNodeAnalyzer->isUsed($node, $variable));
176-
}
177-
private function removeForeachValueAndUseArrayKeys(Foreach_ $foreach, Expr $keyVarExpr): void
178-
{
179-
// remove key value
180-
$foreach->valueVar = $keyVarExpr;
181-
$foreach->keyVar = null;
182-
$foreach->expr = $this->nodeFactory->createFuncCall('array_keys', [$foreach->expr]);
58+
throw new ShouldNotHappenException(sprintf('"%s" rule is deprecated, as it is a personal preference that makes foreach harder to read and extend', self::class));
18359
}
18460
}

src/Application/VersionResolver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ final class VersionResolver
1919
* @api
2020
* @var string
2121
*/
22-
public const PACKAGE_VERSION = '952266b6d64f923f9d6d4390e423e4ab65a953c6';
22+
public const PACKAGE_VERSION = '72f8056755dc28dd1a8ab8f39900259f129ebae8';
2323
/**
2424
* @api
2525
* @var string
2626
*/
27-
public const RELEASE_DATE = '2026-08-03 17:19:03';
27+
public const RELEASE_DATE = '2026-08-03 17:33:41';
2828
/**
2929
* @var int
3030
*/

src/Config/Level/CodeQualityLevel.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
use Rector\CodeQuality\Rector\Foreach_\ForeachItemsAssignToEmptyArrayToAssignRector;
3232
use Rector\CodeQuality\Rector\Foreach_\ForeachToInArrayRector;
3333
use Rector\CodeQuality\Rector\Foreach_\SimplifyForeachToCoalescingRector;
34-
use Rector\CodeQuality\Rector\Foreach_\UnusedForeachValueToArrayKeysRector;
3534
use Rector\CodeQuality\Rector\FuncCall\ArrayMergeOfNonArraysToSimpleArrayRector;
3635
use Rector\CodeQuality\Rector\FuncCall\CallUserFuncWithArrowFunctionToInlineRector;
3736
use Rector\CodeQuality\Rector\FuncCall\ChangeArrayPushToArrayAssignRector;
@@ -100,7 +99,7 @@ final class CodeQualityLevel
10099
*
101100
* @var array<class-string<RectorInterface>>
102101
*/
103-
public const RULES = [FixClassCaseSensitivityVarDocblockRector::class, CombinedAssignRector::class, NewArrayItemConcatAssignToAssignRector::class, SimplifyEmptyArrayCheckRector::class, ReplaceMultipleBooleanNotRector::class, ReplaceConstantBooleanNotRector::class, ForeachToInArrayRector::class, RepeatedOrEqualToInArrayRector::class, RepeatedAndNotEqualToNotInArrayRector::class, MoveInnerFunctionToTopLevelRector::class, InnerFunctionToPrivateMethodRector::class, SimplifyForeachToCoalescingRector::class, SimplifyFuncGetArgsCountRector::class, SimplifyInArrayValuesRector::class, SimplifyStrposLowerRector::class, SimplifyArraySearchRector::class, SimplifyConditionsRector::class, SimplifyIfNotNullReturnRector::class, SimplifyIfReturnBoolRector::class, UnnecessaryTernaryExpressionRector::class, RemoveExtraParametersRector::class, SimplifyDeMorganBinaryRector::class, NegatedAndsToPositiveOrsRector::class, SimplifyTautologyTernaryRector::class, TernaryConditionVariableAssignmentRector::class, SingleInArrayToCompareRector::class, TernaryImplodeToImplodeRector::class, ConsecutiveNullCompareReturnsToNullCoalesceQueueRector::class, UseIdenticalOverEqualWithSameTypeRector::class, SimplifyBoolIdenticalTrueRector::class, BooleanNotIdenticalToNotIdenticalRector::class, AndAssignsToSeparateLinesRector::class, CompactToVariablesRector::class, CompleteDynamicPropertiesRector::class, IsAWithStringWithThirdArgumentRector::class, StrlenZeroToIdenticalEmptyStringRector::class, ThrowWithPreviousExceptionRector::class, RemoveSoleValueSprintfRector::class, ExplicitReturnNullRector::class, ArrayMergeOfNonArraysToSimpleArrayRector::class, ArrayKeyExistsTernaryThenValueToCoalescingRector::class, AbsolutizeRequireAndIncludePathRector::class, ChangeArrayPushToArrayAssignRector::class, ForRepeatedCountToOwnVariableRector::class, ForeachItemsAssignToEmptyArrayToAssignRector::class, UnusedForeachValueToArrayKeysRector::class, CommonNotEqualRector::class, SetTypeToCastRector::class, LogicalToBooleanRector::class, VarToPublicPropertyRector::class, IssetOnPropertyObjectToPropertyExistsRector::class, NewStaticToNewSelfRector::class, UnwrapSprintfOneArgumentRector::class, VariableConstFetchToClassConstFetchRector::class, SwitchNegatedTernaryRector::class, SingularSwitchToIfRector::class, SwitchTrueToMatchRector::class, SimplifyIfNullableReturnRector::class, CallUserFuncWithArrowFunctionToInlineRector::class, FlipTypeControlToUseExclusiveTypeRector::class, InlineArrayReturnAssignRector::class, InlineIsAInstanceOfRector::class, InlineConstructorDefaultToPropertyRector::class, TernaryEmptyArrayArrayDimFetchToCoalesceRector::class, OptionalParametersAfterRequiredRector::class, SimplifyEmptyCheckOnEmptyArrayRector::class, CleanupUnneededNullsafeOperatorRector::class, DisallowedEmptyRuleFixerRector::class, LocallyCalledStaticMethodToNonStaticRector::class, NumberCompareToMaxFuncCallRector::class, RemoveUselessIsObjectCheckRector::class, ConvertStaticToSelfRector::class, SortCallLikeNamedArgsRector::class, SortAttributeNamedArgsRector::class, RemoveReadonlyPropertyVisibilityOnReadonlyClassRector::class, SafeDeclareStrictTypesRector::class];
102+
public const RULES = [FixClassCaseSensitivityVarDocblockRector::class, CombinedAssignRector::class, NewArrayItemConcatAssignToAssignRector::class, SimplifyEmptyArrayCheckRector::class, ReplaceMultipleBooleanNotRector::class, ReplaceConstantBooleanNotRector::class, ForeachToInArrayRector::class, RepeatedOrEqualToInArrayRector::class, RepeatedAndNotEqualToNotInArrayRector::class, MoveInnerFunctionToTopLevelRector::class, InnerFunctionToPrivateMethodRector::class, SimplifyForeachToCoalescingRector::class, SimplifyFuncGetArgsCountRector::class, SimplifyInArrayValuesRector::class, SimplifyStrposLowerRector::class, SimplifyArraySearchRector::class, SimplifyConditionsRector::class, SimplifyIfNotNullReturnRector::class, SimplifyIfReturnBoolRector::class, UnnecessaryTernaryExpressionRector::class, RemoveExtraParametersRector::class, SimplifyDeMorganBinaryRector::class, NegatedAndsToPositiveOrsRector::class, SimplifyTautologyTernaryRector::class, TernaryConditionVariableAssignmentRector::class, SingleInArrayToCompareRector::class, TernaryImplodeToImplodeRector::class, ConsecutiveNullCompareReturnsToNullCoalesceQueueRector::class, UseIdenticalOverEqualWithSameTypeRector::class, SimplifyBoolIdenticalTrueRector::class, BooleanNotIdenticalToNotIdenticalRector::class, AndAssignsToSeparateLinesRector::class, CompactToVariablesRector::class, CompleteDynamicPropertiesRector::class, IsAWithStringWithThirdArgumentRector::class, StrlenZeroToIdenticalEmptyStringRector::class, ThrowWithPreviousExceptionRector::class, RemoveSoleValueSprintfRector::class, ExplicitReturnNullRector::class, ArrayMergeOfNonArraysToSimpleArrayRector::class, ArrayKeyExistsTernaryThenValueToCoalescingRector::class, AbsolutizeRequireAndIncludePathRector::class, ChangeArrayPushToArrayAssignRector::class, ForRepeatedCountToOwnVariableRector::class, ForeachItemsAssignToEmptyArrayToAssignRector::class, CommonNotEqualRector::class, SetTypeToCastRector::class, LogicalToBooleanRector::class, VarToPublicPropertyRector::class, IssetOnPropertyObjectToPropertyExistsRector::class, NewStaticToNewSelfRector::class, UnwrapSprintfOneArgumentRector::class, VariableConstFetchToClassConstFetchRector::class, SwitchNegatedTernaryRector::class, SingularSwitchToIfRector::class, SwitchTrueToMatchRector::class, SimplifyIfNullableReturnRector::class, CallUserFuncWithArrowFunctionToInlineRector::class, FlipTypeControlToUseExclusiveTypeRector::class, InlineArrayReturnAssignRector::class, InlineIsAInstanceOfRector::class, InlineConstructorDefaultToPropertyRector::class, TernaryEmptyArrayArrayDimFetchToCoalesceRector::class, OptionalParametersAfterRequiredRector::class, SimplifyEmptyCheckOnEmptyArrayRector::class, CleanupUnneededNullsafeOperatorRector::class, DisallowedEmptyRuleFixerRector::class, LocallyCalledStaticMethodToNonStaticRector::class, NumberCompareToMaxFuncCallRector::class, RemoveUselessIsObjectCheckRector::class, ConvertStaticToSelfRector::class, SortCallLikeNamedArgsRector::class, SortAttributeNamedArgsRector::class, RemoveReadonlyPropertyVisibilityOnReadonlyClassRector::class, SafeDeclareStrictTypesRector::class];
104103
/**
105104
* @var array<class-string<RectorInterface>, mixed[]>
106105
*/

0 commit comments

Comments
 (0)