22
33import com .intellij .openapi .project .DumbService ;
44import com .intellij .openapi .project .Project ;
5+ import com .intellij .patterns .PlatformPatterns ;
56import com .intellij .psi .PsiElement ;
6- import com .jetbrains . php . PhpClassHierarchyUtils ;
7+ import com .intellij . psi . PsiRecursiveElementVisitor ;
78import com .jetbrains .php .PhpIndex ;
89import com .jetbrains .php .lang .documentation .phpdoc .psi .PhpDocComment ;
910import com .jetbrains .php .lang .documentation .phpdoc .psi .tags .PhpDocParamTag ;
1213import com .jetbrains .php .lang .psi .resolve .types .PhpTypeProvider3 ;
1314import org .jetbrains .annotations .Nullable ;
1415
16+ import java .util .ArrayList ;
1517import java .util .Collection ;
18+ import java .util .List ;
1619import java .util .Set ;
1720import java .util .regex .Matcher ;
1821import java .util .regex .Pattern ;
1922
2023public class ExtbaseModelCollectionReturnTypeProvider implements PhpTypeProvider3 {
2124
22- public static final String TYPO3_CMS_EXTBASE_DOMAIN_OBJECT_ABSTRACT_ENTITY = "TYPO3\\ CMS\\ Extbase\\ DomainObject\\ AbstractEntity" ;
23-
24- @ Override
25- public char getKey () {
26- return '\u0278' ;
27- }
2825
2926 @ Nullable
30- @ Override
31- public PhpType getType (PsiElement psiElement ) {
32- if (DumbService .getInstance (psiElement .getProject ()).isDumb ()) {
33- return null ;
34- }
35-
36- if (!(psiElement instanceof Field ) && !isGetter (psiElement )) {
37- return null ;
38- }
39-
40- if (!isEntityClass (psiElement )) {
41- return null ;
42- }
43-
44- return extractReturnType (psiElement );
45- }
46-
47- private PhpType extractReturnType (PsiElement psiElement ) {
48- Field field ;
49- if (psiElement instanceof MethodReference ) {
50- field = extractFieldFromGetter ((MethodReference ) psiElement );
51- } else if (psiElement instanceof Method ) {
52- field = extractFieldFromGetter ((Method ) psiElement );
53- } else {
54- field = ((Field ) psiElement );
55- }
56-
57- if (field == null ) {
27+ private static PhpType inferTypeFromClassMember (PhpClassMember classMember ) {
28+ if (classMember == null ) {
5829 return null ;
5930 }
6031
61- PhpDocComment docComment = field .getDocComment ();
32+ PhpDocComment docComment = classMember .getDocComment ();
6233 if (docComment == null ) {
6334 return null ;
6435 }
@@ -85,6 +56,31 @@ private PhpType extractReturnType(PsiElement psiElement) {
8556 return phpType ;
8657 }
8758
59+ @ Override
60+ public char getKey () {
61+ return '\u0278' ;
62+ }
63+
64+ @ Nullable
65+ @ Override
66+ public PhpType getType (PsiElement psiElement ) {
67+ if (DumbService .getInstance (psiElement .getProject ()).isDumb ()) {
68+ return null ;
69+ }
70+
71+ if (psiElement instanceof FieldReference ) {
72+ String signature = ((FieldReference ) psiElement ).getSignature ();
73+ return new PhpType ().add ("#" + this .getKey () + signature );
74+ }
75+
76+ if (psiElement instanceof MethodReference && ((MethodReference ) psiElement ).getName ().startsWith ("get" )) {
77+ String signature = ((MethodReference ) psiElement ).getSignature ();
78+ return new PhpType ().add ("#" + this .getKey () + signature );
79+ }
80+
81+ return null ;
82+ }
83+
8884 private Field extractFieldFromGetter (MethodReference methodReference ) {
8985 String name = methodReference .getName ();
9086 if (name == null ) {
@@ -127,27 +123,62 @@ private Field extractFieldFromGetter(Method method) {
127123 return containingClass .findFieldByName (propertyName , false );
128124 }
129125
130- private boolean isEntityClass (PsiElement psiElement ) {
131- PhpClass containingClass = ((PhpClassMember ) psiElement ).getContainingClass ();
132- if (containingClass == null ) {
133- return false ;
134- }
126+ @ Override
127+ public Collection <? extends PhpNamedElement > getBySignature (String expression , Set <String > visited , int depth , Project project ) {
128+ Collection <? extends PhpNamedElement > bySignature = PhpIndex .getInstance (project ).getBySignature (expression );
129+
130+ List <PhpNamedElement > phpNamedElements = new ArrayList <>();
131+ for (PhpNamedElement phpNamedElement : bySignature ) {
132+ if (phpNamedElement instanceof Field ) {
133+ PhpType type = inferTypeFromClassMember ((Field ) phpNamedElement );
134+ phpNamedElement .getType ().add (type );
135+
136+ phpNamedElements .add (phpNamedElement );
137+ } else if (phpNamedElement instanceof Method ) {
138+ phpNamedElement .getType ().add (inferTypeFromClassMember ((Method ) phpNamedElement ));
139+ phpNamedElement .getType ().add (inferTypeFromClassMember (extractFieldFromGetter ((Method ) phpNamedElement )));
135140
136- Collection <PhpClass > classesByFQN = PhpIndex .getInstance (psiElement .getProject ()).getClassesByFQN (TYPO3_CMS_EXTBASE_DOMAIN_OBJECT_ABSTRACT_ENTITY );
137- if (classesByFQN .isEmpty ()) {
138- return false ;
141+ MethodReturnTypeVisitor visitor = new MethodReturnTypeVisitor ();
142+ visitor .visitElement (phpNamedElement );
143+
144+ phpNamedElement .getType ().add (visitor .getType ());
145+
146+ phpNamedElements .add (phpNamedElement );
147+ } else if (phpNamedElement instanceof MethodReference ) {
148+ phpNamedElement .getType ().add (inferTypeFromClassMember (extractFieldFromGetter ((MethodReference ) phpNamedElement )));
149+
150+ phpNamedElements .add (phpNamedElement );
151+ }
139152 }
140153
141- PhpClass abstractEntityClass = classesByFQN .iterator ().next ();
142- return PhpClassHierarchyUtils .isSuperClass (abstractEntityClass , containingClass , true );
154+ return phpNamedElements ;
143155 }
144156
145- private boolean isGetter (PsiElement psiElement ) {
146- return (psiElement instanceof Method ) && ((Method ) psiElement ).getName ().startsWith ("get" );
147- }
157+ private static class MethodReturnTypeVisitor extends PsiRecursiveElementVisitor {
158+ private final PhpType type ;
148159
149- @ Override
150- public Collection <? extends PhpNamedElement > getBySignature (String expression , Set <String > visited , int depth , Project project ) {
151- return PhpIndex .getInstance (project ).getBySignature (expression );
160+ public MethodReturnTypeVisitor () {
161+ super ();
162+
163+ this .type = new PhpType ();
164+ }
165+
166+ @ Override
167+ public void visitElement (PsiElement element ) {
168+ super .visitElement (element );
169+
170+ if (PlatformPatterns .psiElement (FieldReference .class ).withParent (PhpReturn .class ).accepts (element )) {
171+ Field f = (Field ) ((FieldReference ) element ).resolve ();
172+ if (f == null ) {
173+ return ;
174+ }
175+
176+ this .type .add (inferTypeFromClassMember (f ));
177+ }
178+ }
179+
180+ public PhpType getType () {
181+ return type ;
182+ }
152183 }
153184}
0 commit comments