Skip to content

Commit f439ed0

Browse files
committed
Separate Extbase Persistence Completion Contributors
1 parent 6bb4139 commit f439ed0

File tree

7 files changed

+135
-105
lines changed

7 files changed

+135
-105
lines changed

src/main/java/com/cedricziel/idea/typo3/extbase/ExtbaseUtils.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,28 @@
1515
import java.util.Collection;
1616
import java.util.Iterator;
1717

18-
import static com.cedricziel.idea.typo3.extbase.persistence.ExtbasePersistenceCompletionContributor.ExtbaseRepositoryMagicMethodsCompletionProvider.TYPO3_CMS_EXTBASE_PERSISTENCE_REPOSITORY;
19-
2018
public class ExtbaseUtils {
2119
public static final String EXTBASE_ABSTRACT_ENTITY_FQN = "TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity";
2220

2321
public static String EXTBASE_QUERY_INTERFACE_FQN = "TYPO3\\CMS\\Extbase\\Persistence\\QueryInterface";
2422

25-
private static final String OBJECT_STORAGE_FQN = "TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage";
23+
public static String[] EXTBASE_QUERY_BUILDER_METHODS = {
24+
"equals",
25+
"like",
26+
"contains",
27+
"in",
28+
"lessThan",
29+
"lessThanOrEqual",
30+
"greaterThan",
31+
"greaterThanOrEqual",
32+
"isEmpty",
33+
};
34+
35+
public static final String OBJECT_STORAGE_FQN = "TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage";
36+
37+
public static final String TYPO3_CMS_EXTBASE_PERSISTENCE_REPOSITORY = "TYPO3\\CMS\\Extbase\\Persistence\\Repository";
38+
39+
public static final String QUERY_RESULT_INTERFACE = "TYPO3\\CMS\\Extbase\\Persistence\\QueryResultInterface";
2640

2741
public static final String[] NON_QUERYABLE_ENTITY_FIELDS = {
2842
"_isClone",

src/main/java/com/cedricziel/idea/typo3/extbase/persistence/ExtbasePersistenceReferenceResolver.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.cedricziel.idea.typo3.extbase.persistence;
22

3+
import com.cedricziel.idea.typo3.extbase.ExtbaseUtils;
34
import com.cedricziel.idea.typo3.psi.PhpElementsUtil;
45
import com.cedricziel.idea.typo3.util.ExtbaseUtility;
56
import com.intellij.psi.util.PsiTreeUtil;
@@ -13,8 +14,6 @@
1314
import java.util.Collections;
1415
import java.util.List;
1516

16-
import static com.cedricziel.idea.typo3.extbase.persistence.ExtbasePersistenceCompletionContributor.ExtbaseRepositoryMagicMethodsCompletionProvider.TYPO3_CMS_EXTBASE_PERSISTENCE_REPOSITORY;
17-
1817
public class ExtbasePersistenceReferenceResolver implements PhpReferenceResolver {
1918
@Override
2019
public Collection<? extends PhpNamedElement> resolve(PhpReference phpReference) {
@@ -45,7 +44,7 @@ public Collection<? extends PhpNamedElement> resolve(PhpReference phpReference)
4544
}
4645

4746
classesByFQN.forEach(repositoryClass -> {
48-
if (!PhpElementsUtil.hasSuperClass(repositoryClass, TYPO3_CMS_EXTBASE_PERSISTENCE_REPOSITORY)) {
47+
if (!PhpElementsUtil.hasSuperClass(repositoryClass, ExtbaseUtils.TYPO3_CMS_EXTBASE_PERSISTENCE_REPOSITORY)) {
4948
return;
5049
}
5150

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.cedricziel.idea.typo3.extbase.persistence.codeInsight;
2+
3+
import com.cedricziel.idea.typo3.extbase.ExtbasePatterns;
4+
import com.cedricziel.idea.typo3.extbase.ExtbaseUtils;
5+
import com.cedricziel.idea.typo3.util.ExtbaseUtility;
6+
import com.intellij.codeInsight.completion.*;
7+
import com.intellij.patterns.PlatformPatterns;
8+
import com.intellij.psi.PsiElement;
9+
import com.intellij.psi.util.PsiTreeUtil;
10+
import com.intellij.util.ProcessingContext;
11+
import com.jetbrains.php.PhpIndex;
12+
import com.jetbrains.php.completion.PhpLookupElement;
13+
import com.jetbrains.php.lang.psi.elements.Method;
14+
import com.jetbrains.php.lang.psi.elements.MethodReference;
15+
import com.jetbrains.php.lang.psi.elements.PhpClass;
16+
import org.jetbrains.annotations.NotNull;
17+
18+
import java.util.Arrays;
19+
import java.util.Collection;
20+
21+
public class QueryCompletionContributor extends CompletionContributor {
22+
public QueryCompletionContributor() {
23+
this.extend(CompletionType.BASIC, ExtbasePatterns.stringArgumentOnMethodCallPattern(), new QueryCompletionProvider());
24+
}
25+
26+
public static class QueryCompletionProvider extends CompletionProvider<CompletionParameters> {
27+
28+
@Override
29+
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) {
30+
PsiElement element = parameters.getOriginalPosition();
31+
32+
Method containingMethod = (Method) PsiTreeUtil.findFirstParent(element, x -> PlatformPatterns.psiElement(Method.class).accepts(x));
33+
MethodReference methodReference = (MethodReference) PsiTreeUtil.findFirstParent(element, x -> PlatformPatterns.psiElement(MethodReference.class).accepts(x));
34+
35+
if (containingMethod == null || methodReference == null) {
36+
return;
37+
}
38+
39+
Method method = (Method) methodReference.resolve();
40+
if (method == null || method.getContainingClass() == null) {
41+
return;
42+
}
43+
44+
if (!Arrays.asList(ExtbaseUtils.EXTBASE_QUERY_BUILDER_METHODS).contains(method.getName())) {
45+
return;
46+
}
47+
48+
PhpClass repositoryClass = containingMethod.getContainingClass();
49+
if (repositoryClass == null || !ExtbaseUtils.isRepositoryClass(repositoryClass)) {
50+
return;
51+
}
52+
53+
if (!ExtbaseUtils.methodInstanceOf(ExtbaseUtils.EXTBASE_QUERY_INTERFACE_FQN, method)) {
54+
return;
55+
}
56+
57+
String potentialModelClass = ExtbaseUtility.convertRepositoryFQNToEntityFQN(repositoryClass.getFQN());
58+
Collection<PhpClass> classesByFQN = PhpIndex.getInstance(element.getProject()).getClassesByFQN(potentialModelClass);
59+
for (PhpClass x: classesByFQN) {
60+
x.getFields().stream().filter(field -> !Arrays.asList(ExtbaseUtils.NON_QUERYABLE_ENTITY_FIELDS).contains(field.getName())).forEach(field -> result.addElement(new PhpLookupElement(field)));
61+
}
62+
}
63+
}
64+
}

src/main/java/com/cedricziel/idea/typo3/extbase/persistence/ExtbasePersistenceCompletionContributor.java renamed to src/main/java/com/cedricziel/idea/typo3/extbase/persistence/codeInsight/RepositoryMagicMethodsCompletionContributor.java

Lines changed: 4 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,30 @@
1-
package com.cedricziel.idea.typo3.extbase.persistence;
1+
package com.cedricziel.idea.typo3.extbase.persistence.codeInsight;
22

3-
import com.cedricziel.idea.typo3.extbase.ExtbasePatterns;
43
import com.cedricziel.idea.typo3.extbase.ExtbaseUtils;
54
import com.cedricziel.idea.typo3.util.ExtbaseUtility;
65
import com.intellij.codeInsight.completion.*;
76
import com.intellij.codeInsight.lookup.LookupElement;
87
import com.intellij.codeInsight.lookup.LookupElementPresentation;
98
import com.intellij.patterns.PlatformPatterns;
109
import com.intellij.psi.PsiElement;
11-
import com.intellij.psi.util.PsiTreeUtil;
1210
import com.intellij.util.ProcessingContext;
1311
import com.jetbrains.php.PhpIcons;
1412
import com.jetbrains.php.PhpIndex;
15-
import com.jetbrains.php.completion.PhpLookupElement;
1613
import com.jetbrains.php.lang.lexer.PhpTokenTypes;
1714
import com.jetbrains.php.lang.psi.elements.*;
1815
import com.jetbrains.php.lang.psi.resolve.types.PhpType;
1916
import org.apache.commons.lang.StringUtils;
2017
import org.jetbrains.annotations.NotNull;
2118

22-
import java.util.Arrays;
2319
import java.util.Collection;
2420

25-
public class ExtbasePersistenceCompletionContributor extends CompletionContributor {
26-
public ExtbasePersistenceCompletionContributor() {
21+
public class RepositoryMagicMethodsCompletionContributor extends CompletionContributor {
22+
public RepositoryMagicMethodsCompletionContributor() {
2723
this.extend(CompletionType.BASIC, PlatformPatterns.psiElement(PhpTokenTypes.IDENTIFIER), new ExtbaseRepositoryMagicMethodsCompletionProvider());
28-
this.extend(CompletionType.BASIC, ExtbasePatterns.stringArgumentOnMethodCallPattern(), new ExtbaseQueryBuilderCompletionProvider());
2924
}
3025

3126
public static class ExtbaseRepositoryMagicMethodsCompletionProvider extends CompletionProvider<CompletionParameters> {
3227

33-
public static final String TYPO3_CMS_EXTBASE_PERSISTENCE_REPOSITORY = "TYPO3\\CMS\\Extbase\\Persistence\\Repository";
34-
private static final String QUERY_RESULT_INTERFACE = "TYPO3\\CMS\\Extbase\\Persistence\\QueryResultInterface";
35-
3628
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) {
3729
PsiElement position = parameters.getPosition().getOriginalElement();
3830

@@ -82,7 +74,7 @@ public void renderElement(LookupElementPresentation presentation) {
8274
presentation.setTypeText("findBy" + StringUtils.capitalize(f.getName()));
8375
presentation.setIcon(PhpIcons.METHOD_ICON);
8476
presentation.setTailText("(" + f.getName() + " : " + f.getDeclaredType() + ")", true);
85-
presentation.setTypeText(c.getName() + "[]|" + QUERY_RESULT_INTERFACE);
77+
presentation.setTypeText(c.getName() + "[]|" + ExtbaseUtils.QUERY_RESULT_INTERFACE);
8678
}
8779
});
8880

@@ -129,55 +121,4 @@ public void renderElement(LookupElementPresentation presentation) {
129121
});
130122
}
131123
}
132-
133-
public static class ExtbaseQueryBuilderCompletionProvider extends CompletionProvider<CompletionParameters> {
134-
135-
public static String[] QUERY_BUILDER_METHODS = {
136-
"equals",
137-
"like",
138-
"contains",
139-
"in",
140-
"lessThan",
141-
"lessThanOrEqual",
142-
"greaterThan",
143-
"greaterThanOrEqual",
144-
"isEmpty",
145-
};
146-
147-
@Override
148-
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) {
149-
PsiElement element = parameters.getOriginalPosition();
150-
151-
Method containingMethod = (Method) PsiTreeUtil.findFirstParent(element, x -> PlatformPatterns.psiElement(Method.class).accepts(x));
152-
MethodReference methodReference = (MethodReference) PsiTreeUtil.findFirstParent(element, x -> PlatformPatterns.psiElement(MethodReference.class).accepts(x));
153-
154-
if (containingMethod == null || methodReference == null) {
155-
return;
156-
}
157-
158-
Method method = (Method) methodReference.resolve();
159-
if (method == null || method.getContainingClass() == null) {
160-
return;
161-
}
162-
163-
if (!Arrays.asList(QUERY_BUILDER_METHODS).contains(method.getName())) {
164-
return;
165-
}
166-
167-
PhpClass repositoryClass = containingMethod.getContainingClass();
168-
if (repositoryClass == null || !ExtbaseUtils.isRepositoryClass(repositoryClass)) {
169-
return;
170-
}
171-
172-
if (!ExtbaseUtils.methodInstanceOf(ExtbaseUtils.EXTBASE_QUERY_INTERFACE_FQN, method)) {
173-
return;
174-
}
175-
176-
String potentialModelClass = ExtbaseUtility.convertRepositoryFQNToEntityFQN(repositoryClass.getFQN());
177-
Collection<PhpClass> classesByFQN = PhpIndex.getInstance(element.getProject()).getClassesByFQN(potentialModelClass);
178-
for (PhpClass x: classesByFQN) {
179-
x.getFields().stream().filter(field -> !Arrays.asList(ExtbaseUtils.NON_QUERYABLE_ENTITY_FIELDS).contains(field.getName())).forEach(field -> result.addElement(new PhpLookupElement(field)));
180-
}
181-
}
182-
}
183124
}

src/main/resources/META-INF/plugin.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ It is a great inspiration for possible solutions and parts of the code.</p>
214214
<lang.foldingBuilder language="PHP" implementationClass="com.cedricziel.idea.typo3.routing.RouteFoldingBuilder"/>
215215

216216
<!-- extbase persistence -->
217-
<completion.contributor language="PHP" implementationClass="com.cedricziel.idea.typo3.extbase.persistence.ExtbasePersistenceCompletionContributor"/>
217+
<completion.contributor language="PHP" implementationClass="com.cedricziel.idea.typo3.extbase.persistence.codeInsight.QueryCompletionContributor"/>
218+
<completion.contributor language="PHP" implementationClass="com.cedricziel.idea.typo3.extbase.persistence.codeInsight.RepositoryMagicMethodsCompletionContributor"/>
218219

219220
<!-- userFunc -->
220221
<psi.referenceContributor implementation="com.cedricziel.idea.typo3.userFunc.UserFuncReferenceContributor"/>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.cedricziel.idea.typo3.extbase.persistence.codeInsight;
2+
3+
import com.cedricziel.idea.typo3.AbstractTestCase;
4+
import com.intellij.codeInsight.lookup.LookupElement;
5+
6+
public class QueryCompletionContributorTest extends AbstractTestCase {
7+
@Override
8+
protected String getTestDataPath() {
9+
return "testData/com/cedricziel/idea/typo3/extbase/persistence";
10+
}
11+
12+
public void testCanCompleteExtbaseDomainModelFieldsInQuery() {
13+
myFixture.copyFileToProject("PersistenceMocks.php");
14+
15+
LookupElement[] lookupElements;
16+
17+
myFixture.configureByText(
18+
"foo.php",
19+
"<?php\n" +
20+
"namespace My\\Extension\\Domain\\Repository {\n" +
21+
" class BookRepository extends \\TYPO3\\CMS\\Extbase\\Persistence\\Repository {\n" +
22+
" public function fooBar() {\n" +
23+
" /** @var \\TYPO3\\CMS\\Extbase\\Persistence\\QueryInterface $q */" +
24+
" $q = $this->createQuery();\n" +
25+
" $q->matching(\n" +
26+
" $q->equals('<caret>')\n" +
27+
" );\n" +
28+
" }\n" +
29+
" }\n" +
30+
"}"
31+
);
32+
33+
lookupElements = myFixture.completeBasic();
34+
35+
assertContainsLookupElementWithText(lookupElements, "author");
36+
assertContainsLookupElementWithText(lookupElements, "uid");
37+
assertContainsLookupElementWithText(lookupElements, "pid");
38+
assertNotContainsLookupElementWithText(lookupElements, "_cleanProperties");
39+
assertNotContainsLookupElementWithText(lookupElements, "_isClone");
40+
assertContainsLookupElementWithText(lookupElements, "_versionedUid");
41+
assertContainsLookupElementWithText(lookupElements, "_languageUid");
42+
assertContainsLookupElementWithText(lookupElements, "_localizedUid");
43+
}
44+
}

src/test/java/com/cedricziel/idea/typo3/extbase/persistence/ExtbasePersistenceCompletionContributorTest.java renamed to src/test/java/com/cedricziel/idea/typo3/extbase/persistence/codeInsight/RepositoryMagicMethodsCompletionContributorTest.java

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
package com.cedricziel.idea.typo3.extbase.persistence;
1+
package com.cedricziel.idea.typo3.extbase.persistence.codeInsight;
22

33
import com.cedricziel.idea.typo3.AbstractTestCase;
44
import com.intellij.codeInsight.lookup.LookupElement;
55

6-
public class ExtbasePersistenceCompletionContributorTest extends AbstractTestCase {
6+
public class RepositoryMagicMethodsCompletionContributorTest extends AbstractTestCase {
77
@Override
88
protected String getTestDataPath() {
99
return "testData/com/cedricziel/idea/typo3/extbase/persistence";
@@ -62,37 +62,4 @@ public void testCanCompleteExtbaseRepositoryMagicMethodsOnMembers() {
6262
assertContainsLookupElementWithText(lookupElements, "countByAuthor", "(author : string)", "int");
6363
assertNotContainsLookupElementWithText(lookupElements, "countByPublishers");
6464
}
65-
66-
public void testCanCompleteExtbaseDomainModelFieldsInQuery() {
67-
myFixture.copyFileToProject("PersistenceMocks.php");
68-
69-
LookupElement[] lookupElements;
70-
71-
myFixture.configureByText(
72-
"foo.php",
73-
"<?php\n" +
74-
"namespace My\\Extension\\Domain\\Repository {\n" +
75-
" class BookRepository extends \\TYPO3\\CMS\\Extbase\\Persistence\\Repository {\n" +
76-
" public function fooBar() {\n" +
77-
" /** @var \\TYPO3\\CMS\\Extbase\\Persistence\\QueryInterface $q */" +
78-
" $q = $this->createQuery();\n" +
79-
" $q->matching(\n" +
80-
" $q->equals('<caret>')\n" +
81-
" );\n" +
82-
" }\n" +
83-
" }\n" +
84-
"}"
85-
);
86-
87-
lookupElements = myFixture.completeBasic();
88-
89-
assertContainsLookupElementWithText(lookupElements, "author");
90-
assertContainsLookupElementWithText(lookupElements, "uid");
91-
assertContainsLookupElementWithText(lookupElements, "pid");
92-
assertNotContainsLookupElementWithText(lookupElements, "_cleanProperties");
93-
assertNotContainsLookupElementWithText(lookupElements, "_isClone");
94-
assertContainsLookupElementWithText(lookupElements, "_versionedUid");
95-
assertContainsLookupElementWithText(lookupElements, "_languageUid");
96-
assertContainsLookupElementWithText(lookupElements, "_localizedUid");
97-
}
9865
}

0 commit comments

Comments
 (0)