44import com .intellij .codeInspection .ProblemDescriptor ;
55import com .intellij .codeInspection .ProblemHighlightType ;
66import com .intellij .codeInspection .ProblemsHolder ;
7+ import com .intellij .lang .Language ;
8+ import com .intellij .lang .xml .XMLLanguage ;
9+ import com .intellij .openapi .util .NotNullLazyValue ;
710import com .intellij .patterns .PlatformPatterns ;
811import com .intellij .patterns .StandardPatterns ;
912import com .intellij .psi .PsiElement ;
1013import com .intellij .psi .PsiElementVisitor ;
11- import com .intellij .psi .PsiFile ;
12- import com .intellij .psi .PsiRecursiveElementWalkingVisitor ;
1314import com .intellij .psi .util .PsiTreeUtil ;
14- import com .intellij . psi . xml . XmlFile ;
15+ import com .jetbrains . php . lang . PhpLanguage ;
1516import com .jetbrains .php .lang .parser .PhpElementTypes ;
16- import com .jetbrains .php .lang .psi .PhpFile ;
1717import com .jetbrains .php .lang .psi .elements .Method ;
1818import com .jetbrains .php .lang .psi .elements .PhpClass ;
1919import com .jetbrains .php .lang .psi .elements .PhpReturn ;
3333import org .apache .commons .lang .StringUtils ;
3434import org .jetbrains .annotations .NotNull ;
3535import org .jetbrains .annotations .Nullable ;
36+ import org .jetbrains .yaml .YAMLLanguage ;
3637import org .jetbrains .yaml .YAMLTokenTypes ;
37- import org .jetbrains .yaml .psi .* ;
38+ import org .jetbrains .yaml .psi .YAMLScalar ;
3839
3940import java .util .Collection ;
4041import java .util .stream .Collectors ;
@@ -52,66 +53,55 @@ public PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder, bool
5253 }
5354
5455 return new PsiElementVisitor () {
55- @ Override
56- public void visitFile (@ NotNull PsiFile psiFile ) {
57- if (psiFile instanceof XmlFile ) {
58- visitXmlFile (psiFile , holder , new ContainerCollectionResolver .LazyServiceCollector (holder .getProject ()));
59- } else if (psiFile instanceof YAMLFile ) {
60- visitYamlFile (psiFile , holder , new ContainerCollectionResolver .LazyServiceCollector (holder .getProject ()));
61- } else if (psiFile instanceof PhpFile ) {
62- visitPhpFile ((PhpFile ) psiFile , holder );
63- }
64- }
65- };
66- }
56+ private NotNullLazyValue <ContainerCollectionResolver .LazyServiceCollector > serviceCollector ;
6757
68- private void visitPhpFile (PhpFile psiFile , final ProblemsHolder holder ) {
69- psiFile .acceptChildren (new PhpSubscriberRecursiveElementWalkingVisitor (holder ));
70- }
71-
72- private void visitYamlFile (PsiFile psiFile , final ProblemsHolder holder , @ NotNull final ContainerCollectionResolver .LazyServiceCollector lazyServiceCollector ) {
73-
74- psiFile .acceptChildren (new PsiRecursiveElementWalkingVisitor () {
7558 @ Override
7659 public void visitElement (@ NotNull PsiElement element ) {
77- annotateCallMethod (element , holder , lazyServiceCollector );
78- super .visitElement (element );
79- }
80- });
60+ Language language = element .getLanguage ();
8161
82- }
83-
84- private void visitXmlFile (@ NotNull PsiFile psiFile , @ NotNull final ProblemsHolder holder , @ NotNull final ContainerCollectionResolver .LazyServiceCollector lazyServiceCollector ) {
85-
86- psiFile .acceptChildren (new PsiRecursiveElementWalkingVisitor () {
87- @ Override
88- public void visitElement (@ NotNull PsiElement element ) {
89-
90- if (XmlHelper .getTagAttributePattern ("tag" , "method" ).inside (XmlHelper .getInsideTagPattern ("services" )).inFile (XmlHelper .getXmlFilePattern ()).accepts (element ) ||
91- XmlHelper .getTagAttributePattern ("call" , "method" ).inside (XmlHelper .getInsideTagPattern ("services" )).inFile (XmlHelper .getXmlFilePattern ()).accepts (element )
92- )
93- {
94-
95- // attach to text child only
96- PsiElement [] psiElements = element .getChildren ();
97- if (psiElements .length < 2 ) {
98- return ;
62+ if (language == YAMLLanguage .INSTANCE ) {
63+ if (this .serviceCollector == null ) {
64+ this .serviceCollector = NotNullLazyValue .lazy (() -> new ContainerCollectionResolver .LazyServiceCollector (holder .getProject ()));
9965 }
10066
101- String serviceClassValue = XmlHelper .getServiceDefinitionClass (element );
102- if (StringUtils .isNotBlank (serviceClassValue )) {
103- registerMethodProblem (psiElements [1 ], holder , serviceClassValue , lazyServiceCollector );
67+ visitYmlElement (element , holder , this .serviceCollector );
68+ } else if (language == XMLLanguage .INSTANCE ) {
69+ if (this .serviceCollector == null ) {
70+ this .serviceCollector = NotNullLazyValue .lazy (() -> new ContainerCollectionResolver .LazyServiceCollector (holder .getProject ()));
10471 }
10572
73+ visitXmlElement (element , holder , this .serviceCollector );
74+ } else if (language == PhpLanguage .INSTANCE ) {
75+ if (element instanceof StringLiteralExpression stringLiteralExpression ) {
76+ visitPhpElement (stringLiteralExpression , holder );
77+ }
10678 }
10779
10880 super .visitElement (element );
10981 }
110- });
82+ };
83+ }
84+
85+ public void visitXmlElement (@ NotNull PsiElement element , @ NotNull final ProblemsHolder holder , @ NotNull NotNullLazyValue <ContainerCollectionResolver .LazyServiceCollector > collector ) {
86+ boolean isSupportedTag = XmlHelper .getTagAttributePattern ("tag" , "method" ).inside (XmlHelper .getInsideTagPattern ("services" )).inFile (XmlHelper .getXmlFilePattern ()).accepts (element )
87+ || XmlHelper .getTagAttributePattern ("call" , "method" ).inside (XmlHelper .getInsideTagPattern ("services" )).inFile (XmlHelper .getXmlFilePattern ()).accepts (element );
88+
89+ if (isSupportedTag ) {
90+ // attach to text child only
91+ PsiElement [] psiElements = element .getChildren ();
92+ if (psiElements .length < 2 ) {
93+ return ;
94+ }
11195
96+ String serviceClassValue = XmlHelper .getServiceDefinitionClass (element );
97+ if (StringUtils .isNotBlank (serviceClassValue )) {
98+ registerMethodProblem (psiElements [1 ], holder , serviceClassValue , collector );
99+ }
100+
101+ }
112102 }
113103
114- private void visitYamlMethodTagKey (@ NotNull final PsiElement psiElement , @ NotNull ProblemsHolder holder , ContainerCollectionResolver .LazyServiceCollector collector ) {
104+ private void visitYamlMethodTagKey (@ NotNull final PsiElement psiElement , @ NotNull ProblemsHolder holder , @ NotNull NotNullLazyValue < ContainerCollectionResolver .LazyServiceCollector > collector ) {
115105
116106 String methodName = PsiElementUtils .trimQuote (psiElement .getText ());
117107 if (StringUtils .isBlank (methodName )) {
@@ -126,8 +116,7 @@ private void visitYamlMethodTagKey(@NotNull final PsiElement psiElement, @NotNul
126116 registerMethodProblem (psiElement , holder , classValue , collector );
127117 }
128118
129- private void annotateCallMethod (@ NotNull final PsiElement psiElement , @ NotNull ProblemsHolder holder , ContainerCollectionResolver .LazyServiceCollector collector ) {
130-
119+ private void visitYmlElement (@ NotNull final PsiElement psiElement , @ NotNull ProblemsHolder holder , @ NotNull NotNullLazyValue <ContainerCollectionResolver .LazyServiceCollector > collector ) {
131120 if (StandardPatterns .and (
132121 YamlElementPatternHelper .getInsideKeyValue ("tags" ),
133122 YamlElementPatternHelper .getSingleLineScalarKey ("method" )
@@ -140,10 +129,9 @@ private void annotateCallMethod(@NotNull final PsiElement psiElement, @NotNull P
140129 {
141130 visitYamlMethod (psiElement , holder , collector );
142131 }
143-
144132 }
145133
146- private void visitYamlMethod (PsiElement psiElement , ProblemsHolder holder , ContainerCollectionResolver .LazyServiceCollector collector ) {
134+ private void visitYamlMethod (@ NotNull PsiElement psiElement , @ NotNull ProblemsHolder holder , @ NotNull NotNullLazyValue < ContainerCollectionResolver .LazyServiceCollector > collector ) {
147135 if (YamlElementPatternHelper .getInsideKeyValue ("calls" ).accepts (psiElement )) {
148136 PsiElement parent = psiElement .getParent ();
149137 if ((parent instanceof YAMLScalar )) {
@@ -154,11 +142,11 @@ private void visitYamlMethod(PsiElement psiElement, ProblemsHolder holder, Conta
154142 }
155143 }
156144
157- private void registerMethodProblem (final @ NotNull PsiElement psiElement , @ NotNull ProblemsHolder holder , @ NotNull String classKeyValue , ContainerCollectionResolver .LazyServiceCollector collector ) {
158- registerMethodProblem (psiElement , holder , ServiceUtil .getResolvedClassDefinition (psiElement .getProject (), classKeyValue , collector ));
145+ private void registerMethodProblem (final @ NotNull PsiElement psiElement , @ NotNull ProblemsHolder holder , @ NotNull String classKeyValue , @ NotNull NotNullLazyValue < ContainerCollectionResolver .LazyServiceCollector > collector ) {
146+ registerMethodProblem (psiElement , holder , ServiceUtil .getResolvedClassDefinition (psiElement .getProject (), classKeyValue , collector . get () ));
159147 }
160148
161- private void registerMethodProblem (final @ NotNull PsiElement psiElement , @ NotNull ProblemsHolder holder , @ Nullable PhpClass phpClass ) {
149+ private static void registerMethodProblem (final @ NotNull PsiElement psiElement , @ NotNull ProblemsHolder holder , @ Nullable PhpClass phpClass ) {
162150 if (phpClass == null ) {
163151 return ;
164152 }
@@ -232,35 +220,20 @@ private String importIfNecessary(@NotNull PhpClass phpClass, String fqn) {
232220 * );
233221 *
234222 */
235- private class PhpSubscriberRecursiveElementWalkingVisitor extends PsiRecursiveElementWalkingVisitor {
236- private final ProblemsHolder holder ;
237-
238- PhpSubscriberRecursiveElementWalkingVisitor (ProblemsHolder holder ) {
239- this .holder = holder ;
240- }
241-
242- @ Override
243- public void visitElement (@ NotNull PsiElement element ) {
244- super .visitElement (element );
245-
246- if (!(element instanceof StringLiteralExpression )) {
247- return ;
248- }
249-
250- PsiElement arrayValue = element .getParent ();
251- if (arrayValue != null && arrayValue .getNode ().getElementType () == PhpElementTypes .ARRAY_VALUE ) {
252- PhpReturn phpReturn = PsiTreeUtil .getParentOfType (arrayValue , PhpReturn .class );
253- if (phpReturn != null ) {
254- Method method = PsiTreeUtil .getParentOfType (arrayValue , Method .class );
255- if (method != null ) {
256- String name = method .getName ();
257- if ("getSubscribedEvents" .equals (name )) {
258- PhpClass containingClass = method .getContainingClass ();
259- if (containingClass != null && PhpElementsUtil .isInstanceOf (containingClass , "\\ Symfony\\ Component\\ EventDispatcher\\ EventSubscriberInterface" )) {
260- String contents = ((StringLiteralExpression ) element ).getContents ();
261- if (StringUtils .isNotBlank (contents ) && containingClass .findMethodByName (contents ) == null ) {
262- registerMethodProblem (element , holder , containingClass );
263- }
223+ private static void visitPhpElement (@ NotNull StringLiteralExpression element , @ NotNull ProblemsHolder holder ) {
224+ PsiElement arrayValue = element .getParent ();
225+ if (arrayValue != null && arrayValue .getNode ().getElementType () == PhpElementTypes .ARRAY_VALUE ) {
226+ PhpReturn phpReturn = PsiTreeUtil .getParentOfType (arrayValue , PhpReturn .class );
227+ if (phpReturn != null ) {
228+ Method method = PsiTreeUtil .getParentOfType (arrayValue , Method .class );
229+ if (method != null ) {
230+ String name = method .getName ();
231+ if ("getSubscribedEvents" .equals (name )) {
232+ PhpClass containingClass = method .getContainingClass ();
233+ if (containingClass != null && PhpElementsUtil .isInstanceOf (containingClass , "\\ Symfony\\ Component\\ EventDispatcher\\ EventSubscriberInterface" )) {
234+ String contents = element .getContents ();
235+ if (StringUtils .isNotBlank (contents ) && containingClass .findMethodByName (contents ) == null ) {
236+ registerMethodProblem (element , holder , containingClass );
264237 }
265238 }
266239 }
0 commit comments