Skip to content

Commit f0539a2

Browse files
authored
Merge pull request #1473 from Haehnchen/feature/doctrine-magic-method
support type resolving for magic Doctrine methods "findBy*" "findOneBy*" #149
2 parents aedbfdc + c92446c commit f0539a2

File tree

4 files changed

+61
-9
lines changed

4 files changed

+61
-9
lines changed

src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@
1616
import fr.adrienbrault.idea.symfony2plugin.util.PhpTypeProviderUtil;
1717
import org.jetbrains.annotations.NotNull;
1818
import org.jetbrains.annotations.Nullable;
19-
import java.util.Arrays;
20-
import java.util.Collection;
21-
import java.util.HashSet;
22-
import java.util.Set;
19+
20+
import java.util.*;
2321
import java.util.stream.Collectors;
2422

2523
/**
@@ -63,7 +61,8 @@ public PhpType getType(PsiElement e) {
6361
}
6462

6563
String methodRefName = methodRef.getName();
66-
if(null == methodRefName || !Arrays.asList(new String[] {"find", "findOneBy", "findAll", "findBy"}).contains(methodRefName)) {
64+
65+
if(null == methodRefName || (!Arrays.asList(new String[] {"find", "findAll"}).contains(methodRefName) && !methodRefName.startsWith("findOneBy") && !methodRefName.startsWith("findBy"))) {
6766
return null;
6867
}
6968

@@ -109,7 +108,7 @@ public PhpType complete(String s, Project project) {
109108

110109
PhpIndex phpIndex = PhpIndex.getInstance(project);
111110

112-
Collection<? extends PhpNamedElement> typeSignature = PhpTypeProviderUtil.getTypeSignature(phpIndex, originalSignature);
111+
Collection<? extends PhpNamedElement> typeSignature = getTypeSignatureMagic(phpIndex, originalSignature);
113112

114113
// ->getRepository(SecondaryMarket::class)->findAll() => "findAll", but only if its a instance of this method;
115114
// so non Doctrine method are already filtered
@@ -124,7 +123,7 @@ public PhpType complete(String s, Project project) {
124123
PhpType phpType = new PhpType();
125124

126125
resolveMethods.stream()
127-
.map(name -> name.equals("findAll") || name.equals("findBy") ? phpClass.getFQN() + "[]" : phpClass.getFQN())
126+
.map(name -> name.equals("findAll") || name.startsWith("findBy") ? phpClass.getFQN() + "[]" : phpClass.getFQN())
128127
.collect(Collectors.toSet())
129128
.forEach(phpType::add);
130129

@@ -147,4 +146,33 @@ private Collection<Method> getObjectRepositoryCall(Collection<? extends PhpNamed
147146

148147
return methods;
149148
}
149+
150+
/**
151+
* We can have multiple types inside a TypeProvider; split them on "|" so that we dont get empty types
152+
*
153+
* #M#x#M#C\FooBar.get?doctrine.odm.mongodb.document_manager.getRepository|
154+
* #M#x#M#C\FooBar.get?doctrine.odm.mongodb.document_manager.getRepository
155+
*/
156+
@NotNull
157+
private static Collection<? extends PhpNamedElement> getTypeSignatureMagic(@NotNull PhpIndex phpIndex, @NotNull String signature) {
158+
// magic method resolving; we need to have the ObjectRepository method which does not exists for magic methods, so strip it
159+
// #M#x#M#C\FooBar.get?doctrine.odm.mongodb.document_manager.findByName => findBy
160+
// #M#x#M#C\FooBar.get?doctrine.odm.mongodb.document_manager.findOneBy => findOne
161+
Collection<PhpNamedElement> elements = new HashSet<>();
162+
for (String s : signature.split("\\|")) {
163+
int i = s.lastIndexOf(".");
164+
if (i > 0) {
165+
String substring = s.substring(i + 1);
166+
if (substring.startsWith("findOneBy")) {
167+
s = s.substring(0, i + 1) + "findOneBy";
168+
} else if(substring.startsWith("findBy")) {
169+
s = s.substring(0, i + 1) + "findBy";
170+
}
171+
}
172+
173+
elements.addAll(phpIndex.getBySignature(s, null, 0));
174+
}
175+
176+
return elements;
177+
}
150178
}

src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/querybuilder/QueryBuilderMethodReferenceParser.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import fr.adrienbrault.idea.symfony2plugin.util.PhpTypeProviderUtil;
2424
import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils;
2525
import fr.adrienbrault.idea.symfony2plugin.util.dict.DoctrineModel;
26+
import org.jetbrains.annotations.NotNull;
2627

2728
import java.util.*;
2829
import java.util.regex.Matcher;
@@ -184,7 +185,13 @@ private void collectParameter(QueryBuilderScopeContext qb, MethodReference metho
184185
}
185186

186187

187-
private Map<String, String> findRootDefinition(Collection<MethodReference> methodReferences) {
188+
/**
189+
*
190+
* @param methodReferences
191+
* @return
192+
*/
193+
@NotNull
194+
private Map<String, String> findRootDefinition(@NotNull Collection<MethodReference> methodReferences) {
188195

189196
Map<String, String> roots = new HashMap<>();
190197

src/main/java/fr/adrienbrault/idea/symfony2plugin/util/PhpTypeProviderUtil.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import java.util.ArrayList;
1313
import java.util.Collection;
14+
import java.util.HashSet;
1415

1516
/**
1617
* @author Daniel Espendiller <daniel@espendiller.net>
@@ -172,7 +173,7 @@ public static Collection<? extends PhpNamedElement> getTypeSignature(@NotNull Ph
172173
return phpIndex.getBySignature(signature, null, 0);
173174
}
174175

175-
Collection<PhpNamedElement> elements = new ArrayList<>();
176+
Collection<PhpNamedElement> elements = new HashSet<>();
176177
for (String s : signature.split("\\|")) {
177178
elements.addAll(phpIndex.getBySignature(s, null, 0));
178179
}

src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/doctrine/ObjectRepositoryResultTypeProviderTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,20 @@ public void testThatArrayAccessIsResolved() {
5959
PlatformPatterns.psiElement(Method.class).withName("getId")
6060
);
6161
}
62+
63+
public void testThatClassAsStringIsResolvedForMagicMethods() {
64+
assertPhpReferenceResolveTo(PhpFileType.INSTANCE,
65+
"<?php" +
66+
"/** @var \\Doctrine\\Common\\Persistence\\ObjectManager $om */\n" +
67+
"$om->getRepository('\\Foo\\Bar')->findOneByName('foobar')->get<caret>Id();",
68+
PlatformPatterns.psiElement(Method.class).withName("getId")
69+
);
70+
71+
assertPhpReferenceResolveTo(PhpFileType.INSTANCE,
72+
"<?php" +
73+
"/** @var \\Doctrine\\Common\\Persistence\\ObjectManager $om */\n" +
74+
"$om->getRepository('\\Foo\\Bar')->findByName('foobar')[0]->get<caret>Id();",
75+
PlatformPatterns.psiElement(Method.class).withName("getId")
76+
);
77+
}
6278
}

0 commit comments

Comments
 (0)