|
4 | 4 | namespace Rector\Php81\Rector\ClassMethod; |
5 | 5 |
|
6 | 6 | use PhpParser\Node; |
7 | | -use PhpParser\Node\Expr; |
8 | | -use PhpParser\Node\Expr\BinaryOp\Coalesce; |
9 | | -use PhpParser\Node\NullableType; |
10 | | -use PhpParser\Node\Param; |
11 | 7 | use PhpParser\Node\Stmt\Class_; |
12 | | -use PhpParser\Node\Stmt\ClassMethod; |
13 | | -use PhpParser\Node\Stmt\Property; |
14 | | -use PHPStan\Reflection\ClassReflection; |
15 | | -use Rector\FamilyTree\NodeAnalyzer\ClassChildAnalyzer; |
16 | | -use Rector\NodeManipulator\StmtsManipulator; |
17 | | -use Rector\Php81\NodeAnalyzer\CoalescePropertyAssignMatcher; |
| 8 | +use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; |
| 9 | +use Rector\Exception\ShouldNotHappenException; |
18 | 10 | use Rector\Rector\AbstractRector; |
19 | | -use Rector\Reflection\ReflectionResolver; |
20 | | -use Rector\ValueObject\MethodName; |
21 | 11 | use Rector\ValueObject\PhpVersionFeature; |
22 | 12 | use Rector\VersionBonding\Contract\MinPhpVersionInterface; |
23 | 13 | use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; |
24 | 14 | use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; |
25 | | -/** |
26 | | - * @see \Rector\Tests\Php81\Rector\ClassMethod\NewInInitializerRector\NewInInitializerRectorTest |
27 | | - */ |
28 | | -final class NewInInitializerRector extends AbstractRector implements MinPhpVersionInterface |
| 15 | +final class NewInInitializerRector extends AbstractRector implements MinPhpVersionInterface, DeprecatedInterface |
29 | 16 | { |
30 | | - /** |
31 | | - * @readonly |
32 | | - */ |
33 | | - private ReflectionResolver $reflectionResolver; |
34 | | - /** |
35 | | - * @readonly |
36 | | - */ |
37 | | - private ClassChildAnalyzer $classChildAnalyzer; |
38 | | - /** |
39 | | - * @readonly |
40 | | - */ |
41 | | - private CoalescePropertyAssignMatcher $coalescePropertyAssignMatcher; |
42 | | - /** |
43 | | - * @readonly |
44 | | - */ |
45 | | - private StmtsManipulator $stmtsManipulator; |
46 | | - public function __construct(ReflectionResolver $reflectionResolver, ClassChildAnalyzer $classChildAnalyzer, CoalescePropertyAssignMatcher $coalescePropertyAssignMatcher, StmtsManipulator $stmtsManipulator) |
47 | | - { |
48 | | - $this->reflectionResolver = $reflectionResolver; |
49 | | - $this->classChildAnalyzer = $classChildAnalyzer; |
50 | | - $this->coalescePropertyAssignMatcher = $coalescePropertyAssignMatcher; |
51 | | - $this->stmtsManipulator = $stmtsManipulator; |
52 | | - } |
53 | 17 | public function getRuleDefinition(): RuleDefinition |
54 | 18 | { |
55 | 19 | return new RuleDefinition('Replace property declaration of new state with direct new', [new CodeSample(<<<'CODE_SAMPLE' |
@@ -87,112 +51,10 @@ public function getNodeTypes(): array |
87 | 51 | */ |
88 | 52 | public function refactor(Node $node): ?Node |
89 | 53 | { |
90 | | - if ($this->shouldSkipClass($node)) { |
91 | | - return null; |
92 | | - } |
93 | | - $constructClassMethod = $node->getMethod(MethodName::CONSTRUCT); |
94 | | - if (!$constructClassMethod instanceof ClassMethod) { |
95 | | - return null; |
96 | | - } |
97 | | - $params = $this->resolveParams($constructClassMethod); |
98 | | - if ($params === []) { |
99 | | - return null; |
100 | | - } |
101 | | - $hasChanged = \false; |
102 | | - foreach ((array) $constructClassMethod->stmts as $key => $stmt) { |
103 | | - foreach ($params as $param) { |
104 | | - $paramName = $this->getName($param); |
105 | | - if ($param->type instanceof NullableType && $param->default === null) { |
106 | | - continue; |
107 | | - } |
108 | | - $coalesce = $this->coalescePropertyAssignMatcher->matchCoalesceAssignsToLocalPropertyNamed($stmt, $paramName); |
109 | | - if (!$coalesce instanceof Coalesce) { |
110 | | - continue; |
111 | | - } |
112 | | - if ($this->stmtsManipulator->isVariableUsedInNextStmt($constructClassMethod, $key + 1, $paramName)) { |
113 | | - continue; |
114 | | - } |
115 | | - $param->default = $coalesce->right; |
116 | | - unset($constructClassMethod->stmts[$key]); |
117 | | - $this->processPropertyPromotion($node, $param, $paramName); |
118 | | - $hasChanged = \true; |
119 | | - } |
120 | | - } |
121 | | - if ($hasChanged) { |
122 | | - return $node; |
123 | | - } |
124 | | - return null; |
| 54 | + throw new ShouldNotHappenException(sprintf('"%s" is deprecated as depends on context. Cannot be automated. Use manually where needed instead', self::class)); |
125 | 55 | } |
126 | 56 | public function provideMinPhpVersion(): int |
127 | 57 | { |
128 | 58 | return PhpVersionFeature::NEW_INITIALIZERS; |
129 | 59 | } |
130 | | - /** |
131 | | - * @return Param[] |
132 | | - */ |
133 | | - private function resolveParams(ClassMethod $classMethod): array |
134 | | - { |
135 | | - $params = $this->matchConstructorParams($classMethod); |
136 | | - if ($params === []) { |
137 | | - return []; |
138 | | - } |
139 | | - if ($this->isOverrideAbstractMethod($classMethod)) { |
140 | | - return []; |
141 | | - } |
142 | | - return $params; |
143 | | - } |
144 | | - private function isOverrideAbstractMethod(ClassMethod $classMethod): bool |
145 | | - { |
146 | | - $classReflection = $this->reflectionResolver->resolveClassReflection($classMethod); |
147 | | - $methodName = $this->getName($classMethod); |
148 | | - return $classReflection instanceof ClassReflection && $this->classChildAnalyzer->hasAbstractParentClassMethod($classReflection, $methodName); |
149 | | - } |
150 | | - private function processPropertyPromotion(Class_ $class, Param $param, string $paramName): void |
151 | | - { |
152 | | - foreach ($class->stmts as $key => $stmt) { |
153 | | - if (!$stmt instanceof Property) { |
154 | | - continue; |
155 | | - } |
156 | | - $property = $stmt; |
157 | | - if (!$this->isName($stmt, $paramName)) { |
158 | | - continue; |
159 | | - } |
160 | | - $param->flags = $property->flags; |
161 | | - $param->attrGroups = array_merge($property->attrGroups, $param->attrGroups); |
162 | | - unset($class->stmts[$key]); |
163 | | - } |
164 | | - } |
165 | | - /** |
166 | | - * @return Param[] |
167 | | - */ |
168 | | - private function matchConstructorParams(ClassMethod $classMethod): array |
169 | | - { |
170 | | - // skip empty constructor assigns, as we need those here |
171 | | - if ($classMethod->stmts === null || $classMethod->stmts === []) { |
172 | | - return []; |
173 | | - } |
174 | | - $params = array_filter($classMethod->params, static fn(Param $param): bool => $param->type instanceof NullableType); |
175 | | - if ($params === []) { |
176 | | - return $params; |
177 | | - } |
178 | | - $totalParams = count($classMethod->params); |
179 | | - foreach (array_keys($params) as $key) { |
180 | | - for ($iteration = $key + 1; $iteration < $totalParams; ++$iteration) { |
181 | | - if (isset($classMethod->params[$iteration]) && !$classMethod->params[$iteration]->default instanceof Expr) { |
182 | | - return []; |
183 | | - } |
184 | | - } |
185 | | - } |
186 | | - return $params; |
187 | | - } |
188 | | - private function shouldSkipClass(Class_ $class): bool |
189 | | - { |
190 | | - if ($class->stmts === []) { |
191 | | - return \true; |
192 | | - } |
193 | | - if ($class->isAbstract()) { |
194 | | - return \true; |
195 | | - } |
196 | | - return $class->isAnonymous(); |
197 | | - } |
198 | 60 | } |
0 commit comments