Issues (12)

src/Reflection/Reflection.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SavinMikhail\AddNamedArgumentsRector\Reflection;
6
7
use PhpParser\Node;
8
use PhpParser\Node\Expr\FuncCall;
9
use PhpParser\Node\Expr\MethodCall;
10
use PhpParser\Node\Expr\New_;
11
use PhpParser\Node\Expr\StaticCall;
12
use PhpParser\Node\Name;
13
use PHPStan\Reflection\ClassReflection;
14
use PHPStan\Reflection\ExtendedParameterReflection;
15
use PHPStan\Reflection\ReflectionProvider;
16
use Rector\NodeNameResolver\NodeNameResolver;
17
use Rector\NodeTypeResolver\NodeTypeResolver;
18
use ReflectionException;
19
use ReflectionFunction;
20
use ReflectionFunctionAbstract;
21
22
final readonly class Reflection
0 ignored issues
show
A parse error occurred: Syntax error, unexpected T_READONLY, expecting T_CLASS on line 22 at column 6
Loading history...
23
{
24
    private ParameterReflection $parameterReflection;
25
26 1
    public function __construct(
27
        private ReflectionProvider $reflectionProvider,
28
        protected NodeNameResolver $nodeNameResolver,
29
        protected NodeTypeResolver $nodeTypeResolver,
30
        ?ParameterReflection $parameterReflection = null,
31
    ) {
32 1
        if ($parameterReflection === null) {
33
            $parameterReflection = new ParameterReflection(
34
                reflectionProvider: $reflectionProvider,
35
                nodeNameResolver: $nodeNameResolver,
36
                nodeTypeResolver: $nodeTypeResolver,
37
            );
38
        }
39 1
        $this->parameterReflection = $parameterReflection;
40
    }
41
42
    /**
43
     * @return ExtendedParameterReflection[]
44
     */
45 10
    public function getParameters(Node $node): array
46
    {
47 10
        return $this->parameterReflection->getParameters(node: $node);
48
    }
49
50
    /**
51
     * Resolve the reflection for a function, method/static call, or constructor.
52
     */
53 4
    public static function getFunctionReflection(
54
        FuncCall|StaticCall|MethodCall|New_ $node,
55
        ?ClassReflection $classReflection,
56
    ): null|ReflectionFunctionAbstract|false {
57 4
        if (self::isFuncCall($node)) {
58 1
            return self::resolveFunction($node);
59
        }
60
61 3
        if (self::isMethodOrStaticCall($node, $classReflection)) {
62 2
            return self::resolveMethod($node, $classReflection);
63
        }
64
65 2
        if (self::isConstructorCall($node, $classReflection)) {
66 2
            return self::resolveConstructor($classReflection);
67
        }
68
69
        return null;
70
    }
71
72 4
    private static function isFuncCall(Node $node): bool
73
    {
74 4
        return $node instanceof FuncCall && $node->name instanceof Name;
75
    }
76
77 3
    private static function isMethodOrStaticCall(Node $node, ?ClassReflection $classReflection): bool
78
    {
79 3
        return ($node instanceof MethodCall || $node instanceof StaticCall)
80 3
            && $classReflection !== null
81 3
            && $node->name instanceof Node\Identifier;
82
    }
83
84 2
    private static function isConstructorCall(Node $node, ?ClassReflection $classReflection): bool
85
    {
86 2
        return $node instanceof New_ && $classReflection !== null;
87
    }
88
89 1
    private static function resolveFunction(FuncCall $node): ?ReflectionFunctionAbstract
90
    {
91
        try {
92 1
            return new ReflectionFunction((string) $node->name);
93
        } catch (ReflectionException) {
94
            return null;
95
        }
96
    }
97
98 2
    private static function resolveMethod(
99
        MethodCall|StaticCall $node,
100
        ClassReflection $classReflection,
101
    ): null|ReflectionFunctionAbstract|false {
102 2
        $methodName = $node->name->name;
103
104
        try {
105 2
            $native = $classReflection->getNativeReflection();
106 2
            if (! $native->hasMethod($methodName)) {
107
                return null;
108
            }
109
110 2
            return $native->getMethod($methodName);
111
        } catch (ReflectionException) {
112
            return null;
113
        }
114
    }
115
116 2
    private static function resolveConstructor(ClassReflection $classReflection): ?ReflectionFunctionAbstract
117
    {
118
        try {
119 2
            return $classReflection->getNativeReflection()->getConstructor();
120
        } catch (ReflectionException) {
121
            return null;
122
        }
123
    }
124
125 10
    public function getClassReflection(FuncCall|StaticCall|MethodCall|New_ $node): ?ClassReflection
126
    {
127 10
        if ($node instanceof MethodCall) {
128 2
            $callerType = $this->nodeTypeResolver->getType(node: $node->var);
129 2
            $classReflections = $callerType->getObjectClassReflections();
130
131 2
            return $classReflections[0] ?? null;
132
        }
133
134 9
        if ($node instanceof StaticCall && $node->class instanceof Name) {
135 1
            return $this->fetchClass($node->class);
136
        }
137
138 8
        if ($node instanceof New_ && $node->class instanceof Name) {
139 3
            return $this->fetchClass($node->class);
140
        }
141
142 5
        return null;
143
    }
144
145 4
    private function fetchClass(Name $name): ?ClassReflection
146
    {
147 4
        $className = $this->nodeNameResolver->getName(node: $name);
148
149 4
        return $this->reflectionProvider->hasClass($className)
150 4
            ? $this->reflectionProvider->getClass($className)
151 4
            : null;
152
    }
153
}
154