Skip to content

Commit 8a97a20

Browse files
authored
[Php80] Remove AstResolver usage on AddParamBasedOnParentClassMethodRector (#8196)
1 parent 3ecc536 commit 8a97a20

1 file changed

Lines changed: 85 additions & 39 deletions

File tree

‎rules/Php80/Rector/ClassMethod/AddParamBasedOnParentClassMethodRector.php‎

Lines changed: 85 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,30 @@
66

77
use PhpParser\Comment;
88
use PhpParser\Node;
9+
use PhpParser\Node\Arg;
10+
use PhpParser\Node\Attribute;
11+
use PhpParser\Node\AttributeGroup;
912
use PhpParser\Node\ComplexType;
1013
use PhpParser\Node\Expr;
1114
use PhpParser\Node\Expr\Variable;
1215
use PhpParser\Node\Identifier;
1316
use PhpParser\Node\Name;
17+
use PhpParser\Node\Name\FullyQualified;
1418
use PhpParser\Node\Param;
1519
use PhpParser\Node\Stmt\Class_;
1620
use PhpParser\Node\Stmt\ClassMethod;
21+
use PHPStan\BetterReflection\Reflection\Adapter\ReflectionParameter;
1722
use PHPStan\Reflection\ClassReflection;
23+
use PHPStan\Reflection\ExtendedParameterReflection;
1824
use PHPStan\Reflection\MethodReflection;
25+
use PHPStan\Reflection\ParametersAcceptorSelector;
1926
use Rector\NodeTypeResolver\Node\AttributeKey;
20-
use Rector\PhpParser\AstResolver;
2127
use Rector\PhpParser\Node\BetterNodeFinder;
2228
use Rector\PhpParser\Printer\BetterStandardPrinter;
2329
use Rector\PHPStan\ScopeFetcher;
30+
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
2431
use Rector\Rector\AbstractRector;
32+
use Rector\StaticTypeMapper\StaticTypeMapper;
2533
use Rector\ValueObject\MethodName;
2634
use Rector\ValueObject\PhpVersionFeature;
2735
use Rector\VendorLocker\ParentClassMethodTypeOverrideGuard;
@@ -36,7 +44,7 @@ final class AddParamBasedOnParentClassMethodRector extends AbstractRector implem
3644
{
3745
public function __construct(
3846
private readonly ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard,
39-
private readonly AstResolver $astResolver,
47+
private readonly StaticTypeMapper $staticTypeMapper,
4048
private readonly BetterStandardPrinter $betterStandardPrinter,
4149
private readonly BetterNodeFinder $betterNodeFinder,
4250
) {
@@ -130,13 +138,18 @@ public function refactor(Node $node): ?Node
130138
continue;
131139
}
132140

133-
$parentClassMethod = $this->astResolver->resolveClassMethodFromMethodReflection($parentMethodReflection);
134-
if (! $parentClassMethod instanceof ClassMethod) {
141+
$parentClassReflection = $parentMethodReflection->getDeclaringClass();
142+
$nativeClassReflection = $parentClassReflection->getNativeReflection();
143+
if (! $nativeClassReflection->hasMethod($parentMethodReflection->getName())) {
135144
continue;
136145
}
137146

138147
$currentClassMethodParams = $classMethod->getParams();
139-
$parentClassMethodParams = $parentClassMethod->getParams();
148+
$parentClassMethodParams = $nativeClassReflection->getMethod($parentMethodReflection->getName())
149+
->getParameters();
150+
$parentParameterReflections = ParametersAcceptorSelector::combineAcceptors(
151+
$parentMethodReflection->getVariants()
152+
)->getParameters();
140153

141154
$countCurrentClassMethodParams = count($currentClassMethodParams);
142155
$countParentClassMethodParams = count($parentClassMethodParams);
@@ -148,9 +161,9 @@ public function refactor(Node $node): ?Node
148161
if ($countCurrentClassMethodParams < $countParentClassMethodParams) {
149162
$hasClassMethodChanged = $this->processReplaceClassMethodParams(
150163
$classMethod,
151-
$parentClassMethod,
152164
$currentClassMethodParams,
153-
$parentClassMethodParams
165+
$parentClassMethodParams,
166+
$parentParameterReflections
154167
);
155168

156169
if ($hasClassMethodChanged) {
@@ -178,7 +191,7 @@ public function refactor(Node $node): ?Node
178191

179192
/**
180193
* @param Param[] $currentClassMethodParams
181-
* @param Param[] $parentClassMethodParams
194+
* @param ReflectionParameter[] $parentClassMethodParams
182195
*/
183196
private function processAddNullDefaultParam(
184197
array $currentClassMethodParams,
@@ -208,69 +221,70 @@ private function processAddNullDefaultParam(
208221

209222
/**
210223
* @param array<int, Param> $currentClassMethodParams
211-
* @param array<int, Param> $parentClassMethodParams
224+
* @param array<int, ReflectionParameter> $parentClassMethodParams
225+
* @param array<int, ExtendedParameterReflection> $parentParameterReflections
212226
*/
213227
private function processReplaceClassMethodParams(
214-
ClassMethod $node,
215-
ClassMethod $parentClassMethod,
228+
ClassMethod $classMethod,
216229
array $currentClassMethodParams,
217-
array $parentClassMethodParams
230+
array $parentClassMethodParams,
231+
array $parentParameterReflections
218232
): bool {
219-
$originalParams = $node->params;
233+
$originalParams = $classMethod->params;
220234

221235
$hasChanged = false;
222236

223237
foreach ($parentClassMethodParams as $key => $parentClassMethodParam) {
224238
if (isset($currentClassMethodParams[$key])) {
225239
$currentParamName = $this->getName($currentClassMethodParams[$key]);
226-
$collectParamNamesNextKey = $this->collectParamNamesNextKey($parentClassMethod, $key);
240+
$collectParamNamesNextKey = $this->collectParamNamesNextKey($parentClassMethodParams, $key);
227241

228242
if (in_array($currentParamName, $collectParamNamesNextKey, true)) {
229-
$node->params = $originalParams;
243+
$classMethod->params = $originalParams;
230244
return false;
231245
}
232246

233247
continue;
234248
}
235249

236250
$isUsedInStmts = (bool) $this->betterNodeFinder->findFirstInFunctionLikeScoped(
237-
$node,
251+
$classMethod,
238252
function (Node $subNode) use ($parentClassMethodParam): bool {
239253
if (! $subNode instanceof Variable) {
240254
return false;
241255
}
242256

243-
return $this->nodeComparator->areNodesEqual($subNode, $parentClassMethodParam->var);
257+
return $this->isName($subNode, $parentClassMethodParam->getName());
244258
}
245259
);
246260

247261
if ($isUsedInStmts) {
248-
$node->params = $originalParams;
262+
$classMethod->params = $originalParams;
249263
return false;
250264
}
251265

252-
$paramDefault = $parentClassMethodParam->default;
253-
254-
if ($paramDefault instanceof Expr) {
255-
$paramDefault = $this->nodeFactory->createReprintedNode($paramDefault);
266+
$paramDefault = null;
267+
if ($parentClassMethodParam->isDefaultValueAvailable()) {
268+
$paramDefault = $this->nodeFactory->createReprintedNode(
269+
$parentClassMethodParam->getDefaultValueExpression()
270+
);
256271
}
257272

258-
$paramName = $this->getName($parentClassMethodParam);
259-
$paramType = $this->resolveParamType($parentClassMethodParam);
273+
$paramName = $parentClassMethodParam->getName();
274+
$paramType = $this->resolveParamType($parentParameterReflections[$key] ?? null);
260275

261-
$node->params[$key] = new Param(
276+
$classMethod->params[$key] = new Param(
262277
new Variable($paramName),
263278
$paramDefault,
264279
$paramType,
265-
$parentClassMethodParam->byRef,
266-
$parentClassMethodParam->variadic,
267-
[],
268-
$parentClassMethodParam->flags
280+
$parentClassMethodParam->isPassedByReference(),
281+
$parentClassMethodParam->isVariadic()
269282
);
270283

271-
if ($parentClassMethodParam->attrGroups !== []) {
272-
$attrGroupsAsComment = $this->betterStandardPrinter->print($parentClassMethodParam->attrGroups);
273-
$node->params[$key]->setAttribute(AttributeKey::COMMENTS, [new Comment($attrGroupsAsComment)]);
284+
$attributeGroups = $this->createAttributeGroups($parentClassMethodParam);
285+
if ($attributeGroups !== []) {
286+
$attrGroupsAsComment = $this->betterStandardPrinter->print($attributeGroups);
287+
$classMethod->params[$key]->setAttribute(AttributeKey::COMMENTS, [new Comment($attrGroupsAsComment)]);
274288
}
275289

276290
$hasChanged = true;
@@ -279,28 +293,60 @@ function (Node $subNode) use ($parentClassMethodParam): bool {
279293
return $hasChanged;
280294
}
281295

282-
private function resolveParamType(Param $param): null|Identifier|Name|ComplexType
283-
{
284-
if (! $param->type instanceof Node) {
296+
private function resolveParamType(
297+
?ExtendedParameterReflection $extendedParameterReflection
298+
): null|Identifier|Name|ComplexType {
299+
if (! $extendedParameterReflection instanceof ExtendedParameterReflection) {
285300
return null;
286301
}
287302

288-
return $this->nodeFactory->createReprintedNode($param->type);
303+
return $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode(
304+
$extendedParameterReflection->getNativeType(),
305+
TypeKind::PARAM
306+
);
289307
}
290308

291309
/**
310+
* @param ReflectionParameter[] $parentClassMethodParams
292311
* @return string[]
293312
*/
294-
private function collectParamNamesNextKey(ClassMethod $classMethod, int $key): array
313+
private function collectParamNamesNextKey(array $parentClassMethodParams, int $key): array
295314
{
296315
$paramNames = [];
297316

298-
foreach ($classMethod->params as $paramKey => $param) {
317+
foreach ($parentClassMethodParams as $paramKey => $param) {
299318
if ($paramKey > $key) {
300-
$paramNames[] = $this->getName($param);
319+
$paramNames[] = $param->getName();
301320
}
302321
}
303322

304323
return $paramNames;
305324
}
325+
326+
/**
327+
* @return AttributeGroup[]
328+
*/
329+
private function createAttributeGroups(ReflectionParameter $reflectionParameter): array
330+
{
331+
$attributeGroups = [];
332+
333+
foreach ($reflectionParameter->getAttributes() as $reflectionAttribute) {
334+
$args = [];
335+
foreach ($reflectionAttribute->getArgumentsExpressions() as $name => $argumentExpression) {
336+
$args[] = new Arg(
337+
$this->nodeFactory->createReprintedNode($argumentExpression),
338+
false,
339+
false,
340+
[],
341+
is_string($name) ? new Identifier($name) : null
342+
);
343+
}
344+
345+
$attributeGroups[] = new AttributeGroup([
346+
new Attribute(new FullyQualified($reflectionAttribute->getName()), $args),
347+
]);
348+
}
349+
350+
return $attributeGroups;
351+
}
306352
}

0 commit comments

Comments
 (0)