@@ -39,19 +39,6 @@ public function __construct(
39
39
}
40
40
}
41
41
42
- private function fillDicClasses (ServiceMapFactory $ serviceMapFactory ): void
43
- {
44
- foreach ($ serviceMapFactory ->create ()->getServices () as $ service ) { // @phpstan-ignore phpstanApi.method
45
- $ dicClass = $ service ->getClass ();
46
-
47
- if ($ dicClass === null ) {
48
- continue ;
49
- }
50
-
51
- $ this ->dicClasses [$ dicClass ] = true ;
52
- }
53
- }
54
-
55
42
public function getUsages (Node $ node , Scope $ scope ): array
56
43
{
57
44
if (!$ this ->enabled || !$ node instanceof InClassNode) { // @phpstan-ignore phpstanApi.instanceofAssumption
@@ -81,28 +68,80 @@ public function getUsages(Node $node, Scope $scope): array
81
68
return $ usages ;
82
69
}
83
70
84
- private function shouldMarkAsUsed (ReflectionMethod $ method ): bool
71
+ protected function shouldMarkAsUsed (ReflectionMethod $ method ): bool
72
+ {
73
+ return $ this ->isEventSubscriberMethod ($ method )
74
+ || $ this ->isBundleConstructor ($ method )
75
+ || $ this ->isEventListenerMethodWithAsEventListenerAttribute ($ method )
76
+ || $ this ->isAutowiredWithRequiredAttribute ($ method )
77
+ || $ this ->isConstructorWithAsCommandAttribute ($ method )
78
+ || $ this ->isConstructorWithAsControllerAttribute ($ method )
79
+ || $ this ->isMethodWithRouteAttribute ($ method )
80
+ || $ this ->isProbablySymfonyListener ($ method );
81
+ }
82
+
83
+ protected function fillDicClasses (ServiceMapFactory $ serviceMapFactory ): void
84
+ {
85
+ foreach ($ serviceMapFactory ->create ()->getServices () as $ service ) { // @phpstan-ignore phpstanApi.method
86
+ $ dicClass = $ service ->getClass ();
87
+
88
+ if ($ dicClass === null ) {
89
+ continue ;
90
+ }
91
+
92
+ $ this ->dicClasses [$ dicClass ] = true ;
93
+ }
94
+ }
95
+
96
+ protected function isEventSubscriberMethod (ReflectionMethod $ method ): bool
97
+ {
98
+ // this is simplification, we should deduce that from AST of getSubscribedEvents() method
99
+ return $ method ->getDeclaringClass ()->implementsInterface ('Symfony\Component\EventDispatcher\EventSubscriberInterface ' );
100
+ }
101
+
102
+ protected function isBundleConstructor (ReflectionMethod $ method ): bool
103
+ {
104
+ return $ method ->isConstructor () && $ method ->getDeclaringClass ()->isSubclassOf ('Symfony\Component\HttpKernel\Bundle\Bundle ' );
105
+ }
106
+
107
+ protected function isAutowiredWithRequiredAttribute (ReflectionMethod $ method ): bool
108
+ {
109
+ return $ this ->hasAttribute ($ method , 'Symfony\Contracts\Service\Attribute\Required ' );
110
+ }
111
+
112
+ protected function isEventListenerMethodWithAsEventListenerAttribute (ReflectionMethod $ method ): bool
85
113
{
86
- $ methodName = $ method ->getName ();
87
114
$ class = $ method ->getDeclaringClass ();
88
115
89
- return $ class ->implementsInterface ('Symfony\Component\EventDispatcher\EventSubscriberInterface ' )
90
- || ($ class ->isSubclassOf ('Symfony\Component\HttpKernel\Bundle\Bundle ' ) && $ method ->isConstructor ())
91
- || $ this ->hasAttribute ($ class , 'Symfony\Component\EventDispatcher\Attribute\AsEventListener ' )
92
- || $ this ->hasAttribute ($ method , 'Symfony\Component\EventDispatcher\Attribute\AsEventListener ' )
93
- || $ this ->hasAttribute ($ method , 'Symfony\Contracts\Service\Attribute\Required ' )
94
- || ($ this ->hasAttribute ($ class , 'Symfony\Component\Console\Attribute\AsCommand ' ) && $ method ->isConstructor ())
95
- || ($ this ->hasAttribute ($ class , 'Symfony\Component\HttpKernel\Attribute\AsController ' ) && $ method ->isConstructor ())
96
- || $ this ->hasAttribute ($ method , 'Symfony\Component\Routing\Attribute\Route ' , ReflectionAttribute::IS_INSTANCEOF )
97
- || $ this ->hasAttribute ($ method , 'Symfony\Component\Routing\Annotation\Route ' , ReflectionAttribute::IS_INSTANCEOF )
98
- || $ this ->isProbablySymfonyListener ($ methodName );
116
+ return $ this ->hasAttribute ($ class , 'Symfony\Component\EventDispatcher\Attribute\AsEventListener ' )
117
+ || $ this ->hasAttribute ($ method , 'Symfony\Component\EventDispatcher\Attribute\AsEventListener ' );
118
+ }
119
+
120
+ protected function isConstructorWithAsCommandAttribute (ReflectionMethod $ method ): bool
121
+ {
122
+ $ class = $ method ->getDeclaringClass ();
123
+ return $ method ->isConstructor () && $ this ->hasAttribute ($ class , 'Symfony\Component\Console\Attribute\AsCommand ' );
124
+ }
125
+
126
+ protected function isConstructorWithAsControllerAttribute (ReflectionMethod $ method ): bool
127
+ {
128
+ $ class = $ method ->getDeclaringClass ();
129
+ return $ method ->isConstructor () && $ this ->hasAttribute ($ class , 'Symfony\Component\HttpKernel\Attribute\AsController ' );
130
+ }
131
+
132
+ protected function isMethodWithRouteAttribute (ReflectionMethod $ method ): bool
133
+ {
134
+ return $ this ->hasAttribute ($ method , 'Symfony\Component\Routing\Attribute\Route ' , ReflectionAttribute::IS_INSTANCEOF )
135
+ || $ this ->hasAttribute ($ method , 'Symfony\Component\Routing\Annotation\Route ' , ReflectionAttribute::IS_INSTANCEOF );
99
136
}
100
137
101
138
/**
102
139
* Ideally, we would need to parse DIC xml to know this for sure just like phpstan-symfony does.
103
140
*/
104
- private function isProbablySymfonyListener (string $ methodName ): bool
141
+ protected function isProbablySymfonyListener (ReflectionMethod $ method ): bool
105
142
{
143
+ $ methodName = $ method ->getName ();
144
+
106
145
return $ methodName === 'onKernelResponse '
107
146
|| $ methodName === 'onKernelException '
108
147
|| $ methodName === 'onKernelRequest '
@@ -116,7 +155,7 @@ private function isProbablySymfonyListener(string $methodName): bool
116
155
* @param ReflectionClass<object>|ReflectionMethod $classOrMethod
117
156
* @param ReflectionAttribute::IS_*|0 $flags
118
157
*/
119
- private function hasAttribute (Reflector $ classOrMethod , string $ attributeClass , int $ flags = 0 ): bool
158
+ protected function hasAttribute (Reflector $ classOrMethod , string $ attributeClass , int $ flags = 0 ): bool
120
159
{
121
160
if (PHP_VERSION_ID < 8_00_00 ) {
122
161
return false ;
@@ -143,13 +182,13 @@ private function isSymfonyInstalled(): bool
143
182
|| InstalledVersions::isInstalled ('symfony/http-kernel ' );
144
183
}
145
184
146
- private function createUsage (ExtendedMethodReflection $ getNativeMethod ): ClassMethodUsage
185
+ private function createUsage (ExtendedMethodReflection $ methodReflection ): ClassMethodUsage
147
186
{
148
187
return new ClassMethodUsage (
149
188
null ,
150
189
new ClassMethodRef (
151
- $ getNativeMethod ->getDeclaringClass ()->getName (),
152
- $ getNativeMethod ->getName (),
190
+ $ methodReflection ->getDeclaringClass ()->getName (),
191
+ $ methodReflection ->getName (),
153
192
false ,
154
193
),
155
194
);
0 commit comments