55import com .intellij .psi .util .PsiTreeUtil ;
66import com .jetbrains .php .lang .parser .PhpElementTypes ;
77import com .jetbrains .php .lang .psi .elements .*;
8+ import com .jetbrains .php .lang .psi .stubs .indexes .expectedArguments .PhpExpectedFunctionScalarArgument ;
89import de .espend .idea .php .annotation .dict .PhpDocCommentAnnotation ;
910import de .espend .idea .php .annotation .util .AnnotationUtil ;
1011import fr .adrienbrault .idea .symfony2plugin .doctrine .metadata .util .DoctrineMetadataUtil ;
1112import fr .adrienbrault .idea .symfony2plugin .routing .RouteHelper ;
1213import fr .adrienbrault .idea .symfony2plugin .util .PhpElementsUtil ;
14+ import fr .adrienbrault .idea .symfony2plugin .util .PsiElementUtils ;
1315import fr .adrienbrault .idea .symfony2plugin .util .dict .ServiceUtil ;
1416import org .apache .commons .lang .StringUtils ;
1517import org .jetbrains .annotations .NotNull ;
1618
17- import java .util .*;
19+ import java .util .Arrays ;
20+ import java .util .Collection ;
21+ import java .util .HashSet ;
22+ import java .util .Set ;
1823import java .util .stream .Collectors ;
1924
2025/**
@@ -28,18 +33,19 @@ public class SymfonyImplicitUsageProvider implements ImplicitUsageProvider {
2833
2934 @ Override
3035 public boolean isImplicitUsage (@ NotNull PsiElement element ) {
31- if (element instanceof Method && ((Method ) element ).getAccess () == PhpModifier .Access .PUBLIC ) {
32- return isMethodARoute ((Method ) element )
33- || isSubscribedEvent ((Method ) element );
34- } else if (element instanceof PhpClass ) {
35- return isRouteClass ((PhpClass ) element )
36- || isCommandAndService ((PhpClass ) element )
37- || isSubscribedEvent ((PhpClass ) element )
38- || isVoter ((PhpClass ) element )
39- || isTwigExtension ((PhpClass ) element )
40- || isEntityRepository ((PhpClass ) element )
41- || isConstraint ((PhpClass ) element )
42- || isKernelEventListener ((PhpClass ) element );
36+ if (element instanceof Method method && method .getAccess () == PhpModifier .Access .PUBLIC ) {
37+ return isMethodARoute (method )
38+ || isSubscribedEvent (method )
39+ || isAsEventListenerMethodPhpAttribute (method );
40+ } else if (element instanceof PhpClass phpClass ) {
41+ return isRouteClass (phpClass )
42+ || isCommandAndService (phpClass )
43+ || isSubscribedEvent (phpClass )
44+ || isVoter (phpClass )
45+ || isTwigExtension (phpClass )
46+ || isEntityRepository (phpClass )
47+ || isConstraint (phpClass )
48+ || isKernelEventListener (phpClass );
4349 }
4450
4551 return false ;
@@ -176,4 +182,25 @@ private boolean isSubscribedEvent(@NotNull Method method) {
176182
177183 return false ;
178184 }
185+
186+ private boolean isAsEventListenerMethodPhpAttribute (@ NotNull Method method ) {
187+ PhpClass containingClass = method .getContainingClass ();
188+ if (containingClass == null || !PhpElementsUtil .isInstanceOf (containingClass , "\\ Symfony\\ Component\\ EventDispatcher\\ EventSubscriberInterface" )) {
189+ return false ;
190+ }
191+
192+ for (PhpAttribute attribute : containingClass .getAttributes ("\\ Symfony\\ Component\\ EventDispatcher\\ Attribute\\ AsEventListener" )) {
193+ for (PhpAttribute .PhpAttributeArgument argument : attribute .getArguments ()) {
194+ if ("method" .equals (argument .getName ()) && argument .getArgument () instanceof PhpExpectedFunctionScalarArgument scalarArgument ) {
195+ String value = PsiElementUtils .trimQuote (scalarArgument .getNormalizedValue ());
196+
197+ if (method .getName ().equals (value )) {
198+ return true ;
199+ }
200+ }
201+ }
202+ }
203+
204+ return false ;
205+ }
179206}
0 commit comments