99import com .intellij .psi .PsiFile ;
1010import com .intellij .psi .PsiWhiteSpace ;
1111import com .intellij .util .ThreeState ;
12- import com .jetbrains .php .lang .parser .PhpElementTypes ;
1312import com .jetbrains .php .lang .psi .PhpFile ;
14- import com .jetbrains .php .lang .psi .PhpPsiUtil ;
15- import com .jetbrains .php .lang .psi .elements .*;
1613import fr .adrienbrault .idea .symfony2plugin .Symfony2ProjectComponent ;
1714import org .jetbrains .annotations .NotNull ;
18- import org .jetbrains .annotations .Nullable ;
1915
2016public class PhpAttributeCompletionPopupHandlerCompletionConfidence {
2117 /**
@@ -28,19 +24,23 @@ public static class PhpAttributeCompletionConfidence extends CompletionConfidenc
2824 @ NotNull
2925 @ Override
3026 public ThreeState shouldSkipAutopopup (@ NotNull Editor editor , @ NotNull PsiElement contextElement , @ NotNull PsiFile psiFile , int offset ) {
31- if (offset <= 0 || !(psiFile instanceof PhpFile ) || ! Symfony2ProjectComponent . isEnabled ( editor . getProject ()) ) {
27+ if (offset <= 0 || !(psiFile instanceof PhpFile )) {
3228 return ThreeState .UNSURE ;
3329 }
3430
35- // Check if we're before a method, class, or field
36- if (getMethod ( contextElement ) == null && getPhpClass ( contextElement ) == null && getField ( contextElement ) == null ) {
31+ Project project = editor . getProject ();
32+ if (! Symfony2ProjectComponent . isEnabled ( project ) ) {
3733 return ThreeState .UNSURE ;
3834 }
3935
4036 // Check if there's a "#" before the cursor in the document
4137 CharSequence documentText = editor .getDocument ().getCharsSequence ();
4238 if (documentText .charAt (offset - 1 ) == '#' && psiFile .findElementAt (offset - 2 ) instanceof PsiWhiteSpace ) {
43- return ThreeState .NO ;
39+ // Check if we should provide attribute completions for this context
40+ // (controller class, twig component, twig extension, etc.)
41+ if (PhpAttributeScopeValidator .shouldProvideAttributeCompletions (contextElement , project )) {
42+ return ThreeState .NO ;
43+ }
4444 }
4545
4646 return ThreeState .UNSURE ;
@@ -71,97 +71,14 @@ public static class PhpAttributeAutoPopupHandler extends TypedHandlerDelegate {
7171 return Result .CONTINUE ;
7272 }
7373
74- // Check if we're before a method, class, or field
75- if (getMethod (element ) == null && getField (element ) == null && getPhpClass (element ) == null ) {
74+ // Check if we should provide attribute completions for this context
75+ // (controller class, twig component, twig extension, etc.)
76+ if (!PhpAttributeScopeValidator .shouldProvideAttributeCompletions (element , project )) {
7677 return Result .CONTINUE ;
7778 }
7879
7980 AutoPopupController .getInstance (project ).scheduleAutoPopup (editor );
8081 return Result .STOP ;
8182 }
8283 }
83-
84- /**
85- * Finds a public method associated with the given element.
86- * Returns the method if the element is a child of a method or if the next sibling is a method.
87- *
88- * @param element The PSI element to check
89- * @return The public method if found, null otherwise
90- */
91- public static @ Nullable Method getMethod (@ NotNull PsiElement element ) {
92- Method foundMethod = null ;
93-
94- if (element .getParent () instanceof Method method ) {
95- foundMethod = method ;
96- } else if (PhpPsiUtil .getNextSiblingIgnoreWhitespace (element , true ) instanceof Method method ) {
97- foundMethod = method ;
98- }
99-
100- return foundMethod != null && foundMethod .getAccess ().isPublic ()
101- ? foundMethod
102- : null ;
103- }
104-
105- /**
106- * Finds a PhpClass associated with the given element.
107- * Returns the class if the element is a child of a class or if the next sibling is a class.
108- * Also handles cases where we're in the middle of an attribute list.
109- *
110- * @param element The PSI element to check
111- * @return The PhpClass if found, null otherwise
112- */
113- public static @ Nullable PhpClass getPhpClass (@ NotNull PsiElement element ) {
114- if (element .getParent () instanceof PhpClass phpClass ) {
115- return phpClass ;
116- }
117-
118- // with use statement given
119- PsiElement nextSiblingIgnoreWhitespace = PhpPsiUtil .getNextSiblingIgnoreWhitespace (element , true );
120- if (nextSiblingIgnoreWhitespace instanceof PhpClass phpClass ) {
121- return phpClass ;
122- }
123-
124- // no use statements
125- if (nextSiblingIgnoreWhitespace != null && nextSiblingIgnoreWhitespace .getNode ().getElementType () == PhpElementTypes .NON_LAZY_GROUP_STATEMENT ) {
126- if (nextSiblingIgnoreWhitespace .getFirstChild () instanceof PhpClass phpClass ) {
127- return phpClass ;
128- }
129- }
130-
131- return null ;
132- }
133-
134- /**
135- * Finds a Field (property) associated with the given element.
136- * Returns the field if the element is a child of a field or if the next sibling is a field.
137- *
138- * @param element The PSI element to check
139- * @return The Field if found, null otherwise
140- */
141- public static @ Nullable Field getField (@ NotNull PsiElement element ) {
142- PsiElement nextSiblingIgnoreWhitespace = PhpPsiUtil .getNextSiblingIgnoreWhitespace (element , true );
143- if (nextSiblingIgnoreWhitespace instanceof PhpModifierList phpModifierList && phpModifierList .hasPublic ()) {
144- if (phpModifierList .getNextPsiSibling () instanceof Field field ) {
145- return field ;
146- }
147- }
148-
149- if (nextSiblingIgnoreWhitespace instanceof PhpPsiElement phpPsiElement ) {
150- PhpPsiElement firstPsiChild = phpPsiElement .getFirstPsiChild ();
151- if (firstPsiChild instanceof PhpModifierList phpModifierList && phpModifierList .hasPublic ()) {
152- PhpPsiElement nextPsiSibling = phpModifierList .getNextPsiSibling ();
153-
154- if (nextPsiSibling instanceof Field field ) {
155- return field ;
156- } else if (nextPsiSibling instanceof PhpFieldType phpFieldType ) {
157- PhpPsiElement nextPsiSibling1 = phpFieldType .getNextPsiSibling ();
158- if (nextPsiSibling1 instanceof Field field1 ) {
159- return field1 ;
160- }
161- }
162- }
163- }
164-
165- return null ;
166- }
16784}
0 commit comments