From c604885b43b9c1274198b0d059e390a6373e7652 Mon Sep 17 00:00:00 2001
From: Jack Bentley <jack.bentley@jadu.co.uk>
Date: Thu, 27 Feb 2020 17:26:35 +0000
Subject: [PATCH 1/3] Update TypeProviders to PhpTypeProvider4

---
 .../signature/MethodSignatureTypeProvider.java       |  8 +++++++-
 .../dic/SymfonyContainerTypeProvider.java            |  8 +++++++-
 .../doctrine/ObjectManagerFindTypeProvider.java      |  8 +++++++-
 .../doctrine/ObjectRepositoryResultTypeProvider.java |  9 +++++++--
 .../doctrine/ObjectRepositoryTypeProvider.java       |  9 +++++++--
 .../util/EventDispatcherTypeProvider.java            |  8 +++++++-
 src/main/resources/META-INF/plugin.xml               | 12 ++++++------
 7 files changed, 48 insertions(+), 14 deletions(-)

diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/assistant/signature/MethodSignatureTypeProvider.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/assistant/signature/MethodSignatureTypeProvider.java
index 596db93a6..29edc6914 100644
--- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/assistant/signature/MethodSignatureTypeProvider.java
+++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/assistant/signature/MethodSignatureTypeProvider.java
@@ -11,6 +11,7 @@
 import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
 import com.jetbrains.php.lang.psi.resolve.types.PhpType;
 import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider3;
+import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider4;
 import fr.adrienbrault.idea.symfony2plugin.Settings;
 import fr.adrienbrault.idea.symfony2plugin.extension.MethodSignatureTypeProviderExtension;
 import fr.adrienbrault.idea.symfony2plugin.extension.MethodSignatureTypeProviderParameter;
@@ -27,7 +28,7 @@
  * @author Adrien Brault <adrien.brault@gmail.com>
  * @author Daniel Espendiller <daniel@espendiller.net>
  */
-public class MethodSignatureTypeProvider implements PhpTypeProvider3 {
+public class MethodSignatureTypeProvider implements PhpTypeProvider4 {
 
     final static char TRIM_KEY = '\u0181';
     private static final ExtensionPointName<MethodSignatureTypeProviderExtension> EXTENSIONS = new ExtensionPointName<>("fr.adrienbrault.idea.symfony2plugin.extension.MethodSignatureTypeProviderExtension");
@@ -120,6 +121,11 @@ private Collection<MethodSignatureSetting> getSignatureSetting(String methodName
         return matchedSignatures;
     }
 
+    @Override
+    public PhpType complete(String expression, Project project) {
+        return null;
+    }
+
     @Override
     public Collection<? extends PhpNamedElement> getBySignature(String expression, Set<String> visited, int depth, Project project) {
         // get back our original call
diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/SymfonyContainerTypeProvider.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/SymfonyContainerTypeProvider.java
index 7b66feedb..f3ca64892 100644
--- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/SymfonyContainerTypeProvider.java
+++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/dic/SymfonyContainerTypeProvider.java
@@ -9,6 +9,7 @@
 import com.jetbrains.php.lang.psi.elements.PhpNamedElement;
 import com.jetbrains.php.lang.psi.resolve.types.PhpType;
 import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider3;
+import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider4;
 import fr.adrienbrault.idea.symfony2plugin.Settings;
 import fr.adrienbrault.idea.symfony2plugin.dic.container.util.ServiceContainerUtil;
 import fr.adrienbrault.idea.symfony2plugin.stubs.ContainerCollectionResolver;
@@ -24,7 +25,7 @@
  * @author Adrien Brault <adrien.brault@gmail.com>
  * @author Daniel Espendiller <daniel@espendiller.net>
  */
-public class SymfonyContainerTypeProvider implements PhpTypeProvider3 {
+public class SymfonyContainerTypeProvider implements PhpTypeProvider4 {
     private static char TRIM_KEY = '\u0182';
 
     @Override
@@ -48,6 +49,11 @@ public PhpType getType(PsiElement e) {
         return signature == null ? null : new PhpType().add("#" + this.getKey() + signature);
     }
 
+    @Override
+    public PhpType complete(String expression, Project project) {
+        return null;
+    }
+
     @Override
     public Collection<? extends PhpNamedElement> getBySignature(String expression, Set<String> visited, int depth, Project project) {
 
diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectManagerFindTypeProvider.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectManagerFindTypeProvider.java
index 518b1600b..023f351ba 100644
--- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectManagerFindTypeProvider.java
+++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectManagerFindTypeProvider.java
@@ -10,6 +10,7 @@
 import com.jetbrains.php.lang.psi.elements.PhpNamedElement;
 import com.jetbrains.php.lang.psi.resolve.types.PhpType;
 import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider3;
+import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider4;
 import fr.adrienbrault.idea.symfony2plugin.Settings;
 import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
 import fr.adrienbrault.idea.symfony2plugin.util.PhpTypeProviderUtil;
@@ -24,7 +25,7 @@
  *
  * @author Daniel Espendiller <daniel@espendiller.net>
  */
-public class ObjectManagerFindTypeProvider implements PhpTypeProvider3 {
+public class ObjectManagerFindTypeProvider implements PhpTypeProvider4 {
 
     final static char TRIM_KEY = '\u0183';
 
@@ -62,6 +63,11 @@ public PhpType getType(PsiElement e) {
         return null;
     }
 
+    @Override
+    public PhpType complete(String expression, Project project) {
+        return null;
+    }
+
     @Override
     public Collection<? extends PhpNamedElement> getBySignature(String expression, Set<String> visited, int depth, Project project) {
         // get back our original call
diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java
index e782aaa8c..5baf84eaa 100644
--- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java
+++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java
@@ -11,7 +11,7 @@
 import com.jetbrains.php.lang.psi.elements.PhpClass;
 import com.jetbrains.php.lang.psi.elements.PhpNamedElement;
 import com.jetbrains.php.lang.psi.resolve.types.PhpType;
-import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider3;
+import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider4;
 import fr.adrienbrault.idea.symfony2plugin.Settings;
 import fr.adrienbrault.idea.symfony2plugin.util.MethodMatcher;
 import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
@@ -26,7 +26,7 @@
 /**
  * @author Daniel Espendiller <daniel@espendiller.net>
  */
-public class ObjectRepositoryResultTypeProvider implements PhpTypeProvider3 {
+public class ObjectRepositoryResultTypeProvider implements PhpTypeProvider4 {
     private static MethodMatcher.CallToSignature[] FIND_SIGNATURES = new MethodMatcher.CallToSignature[] {
         new MethodMatcher.CallToSignature("\\Doctrine\\Common\\Persistence\\ObjectRepository", "find"),
         new MethodMatcher.CallToSignature("\\Doctrine\\Common\\Persistence\\ObjectRepository", "findOneBy"),
@@ -105,6 +105,11 @@ public PhpType getType(PsiElement e) {
         return new PhpType().add("#" + this.getKey() + refSignature + TRIM_KEY + repositorySignature);
     }
 
+    @Override
+    public PhpType complete(String expression, Project project) {
+        return null;
+    }
+
     @Override
     public Collection<? extends PhpNamedElement> getBySignature(String expression, Set<String> visited, int depth, Project project) {
         // get back our original call
diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryTypeProvider.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryTypeProvider.java
index 37b014293..9caa374db 100644
--- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryTypeProvider.java
+++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryTypeProvider.java
@@ -9,7 +9,7 @@
 import com.jetbrains.php.lang.psi.elements.PhpClass;
 import com.jetbrains.php.lang.psi.elements.PhpNamedElement;
 import com.jetbrains.php.lang.psi.resolve.types.PhpType;
-import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider3;
+import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider4;
 import fr.adrienbrault.idea.symfony2plugin.Settings;
 import fr.adrienbrault.idea.symfony2plugin.util.MethodMatcher;
 import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
@@ -23,7 +23,7 @@
 /**
  * @author Daniel Espendiller <daniel@espendiller.net>
  */
-public class ObjectRepositoryTypeProvider implements PhpTypeProvider3 {
+public class ObjectRepositoryTypeProvider implements PhpTypeProvider4 {
     private static MethodMatcher.CallToSignature[] GET_REPOSITORIES_SIGNATURES = new MethodMatcher.CallToSignature[] {
         new MethodMatcher.CallToSignature("\\Doctrine\\Common\\Persistence\\ManagerRegistry", "getRepository"),
         new MethodMatcher.CallToSignature("\\Doctrine\\Common\\Persistence\\ObjectManager", "getRepository"),
@@ -59,6 +59,11 @@ public PhpType getType(PsiElement e) {
         return signature == null ? null : new PhpType().add("#" + this.getKey() + signature);
     }
 
+    @Override
+    public PhpType complete(String expression, Project project) {
+        return null;
+    }
+
     @Override
     public Collection<? extends PhpNamedElement> getBySignature(String expression, Set<String> visited, int depth, Project project) {
         // get back our original call
diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/util/EventDispatcherTypeProvider.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/util/EventDispatcherTypeProvider.java
index b1d7da9f5..edba9af28 100644
--- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/util/EventDispatcherTypeProvider.java
+++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/util/EventDispatcherTypeProvider.java
@@ -6,6 +6,7 @@
 import com.jetbrains.php.lang.psi.elements.*;
 import com.jetbrains.php.lang.psi.resolve.types.PhpType;
 import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider3;
+import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider4;
 import fr.adrienbrault.idea.symfony2plugin.Settings;
 import org.apache.commons.lang.StringUtils;
 import org.jetbrains.annotations.Nullable;
@@ -17,7 +18,7 @@
 /**
  * @author Daniel Espendiller <daniel@espendiller.net>
  */
-public class EventDispatcherTypeProvider implements PhpTypeProvider3 {
+public class EventDispatcherTypeProvider implements PhpTypeProvider4 {
 
     private static char TRIM_KEY = '\u0197';
 
@@ -76,6 +77,11 @@ public PhpType getType(PsiElement e) {
         return new PhpType().add("#" + this.getKey() + refSignature + TRIM_KEY + signature);
     }
 
+    @Override
+    public PhpType complete(String expression, Project project) {
+        return null;
+    }
+
     @Override
     public Collection<? extends PhpNamedElement> getBySignature(String expression, Set<String> visited, int depth, Project project) {
         // get back our original call
diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml
index 7b2e4444a..41e56368f 100644
--- a/src/main/resources/META-INF/plugin.xml
+++ b/src/main/resources/META-INF/plugin.xml
@@ -100,12 +100,12 @@
     <idea-version since-build="182.0"/>
 
     <extensions defaultExtensionNs="com.jetbrains.php">
-        <typeProvider3 implementation="fr.adrienbrault.idea.symfony2plugin.dic.SymfonyContainerTypeProvider"/>
-        <typeProvider3 implementation="fr.adrienbrault.idea.symfony2plugin.util.EventDispatcherTypeProvider"/>
-        <typeProvider3 implementation="fr.adrienbrault.idea.symfony2plugin.doctrine.ObjectRepositoryTypeProvider"/>
-        <typeProvider3 implementation="fr.adrienbrault.idea.symfony2plugin.doctrine.ObjectRepositoryResultTypeProvider"/>
-        <typeProvider3 implementation="fr.adrienbrault.idea.symfony2plugin.doctrine.ObjectManagerFindTypeProvider"/>
-        <typeProvider3 implementation="fr.adrienbrault.idea.symfony2plugin.assistant.signature.MethodSignatureTypeProvider"/>
+        <typeProvider4 implementation="fr.adrienbrault.idea.symfony2plugin.dic.SymfonyContainerTypeProvider"/>
+        <typeProvider4 implementation="fr.adrienbrault.idea.symfony2plugin.util.EventDispatcherTypeProvider"/>
+        <typeProvider4 implementation="fr.adrienbrault.idea.symfony2plugin.doctrine.ObjectRepositoryTypeProvider"/>
+        <typeProvider4 implementation="fr.adrienbrault.idea.symfony2plugin.doctrine.ObjectRepositoryResultTypeProvider"/>
+        <typeProvider4 implementation="fr.adrienbrault.idea.symfony2plugin.doctrine.ObjectManagerFindTypeProvider"/>
+        <typeProvider4 implementation="fr.adrienbrault.idea.symfony2plugin.assistant.signature.MethodSignatureTypeProvider"/>
         <libraryRoot id="symfony_meta" path="/symfony-meta/" runtime="false"/>
         <libraryRoot id="doctrine_meta" path="/doctrine-meta/" runtime="false"/>
     </extensions>

From d2178da808269e46ef62a53c22d23f57a87390ce Mon Sep 17 00:00:00 2001
From: Jack Bentley <jack.bentley@jadu.co.uk>
Date: Thu, 27 Feb 2020 17:27:21 +0000
Subject: [PATCH 2/3] Fix doctrine repository find() methods not always
 returning the correct class type hints

---
 .../doctrine/ObjectRepositoryResultTypeProvider.java      | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java
index 5baf84eaa..a3086bf41 100644
--- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java
+++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java
@@ -102,6 +102,14 @@ public PhpType getType(PsiElement e) {
 
         repositorySignature = repositorySignature.substring(1, nextMethodCall);
 
+        if (repositorySignature.startsWith("#K#C")) {
+            repositorySignature = repositorySignature.substring(4);
+        }
+
+        if (repositorySignature.contains(".class")) {
+            repositorySignature = repositorySignature.substring(0, repositorySignature.indexOf(".class"));
+        }
+
         return new PhpType().add("#" + this.getKey() + refSignature + TRIM_KEY + repositorySignature);
     }
 

From cca51fe64682054cdcd5a3c65130048f15cedf31 Mon Sep 17 00:00:00 2001
From: Jack Bentley <jack.bentley@jadu.co.uk>
Date: Fri, 28 Feb 2020 15:53:34 +0000
Subject: [PATCH 3/3] Fix types leaking into other method implementations

---
 .../ObjectRepositoryResultTypeProvider.java     | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java
index a3086bf41..376d94ea3 100644
--- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java
+++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java
@@ -10,6 +10,7 @@
 import com.jetbrains.php.lang.psi.elements.MethodReference;
 import com.jetbrains.php.lang.psi.elements.PhpClass;
 import com.jetbrains.php.lang.psi.elements.PhpNamedElement;
+import com.jetbrains.php.lang.psi.elements.impl.MethodImpl;
 import com.jetbrains.php.lang.psi.resolve.types.PhpType;
 import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider4;
 import fr.adrienbrault.idea.symfony2plugin.Settings;
@@ -102,15 +103,9 @@ public PhpType getType(PsiElement e) {
 
         repositorySignature = repositorySignature.substring(1, nextMethodCall);
 
-        if (repositorySignature.startsWith("#K#C")) {
-            repositorySignature = repositorySignature.substring(4);
-        }
-
-        if (repositorySignature.contains(".class")) {
-            repositorySignature = repositorySignature.substring(0, repositorySignature.indexOf(".class"));
-        }
+        String signature = "#" + this.getKey() + refSignature.substring(0, refSignature.indexOf("|")) + TRIM_KEY + repositorySignature;
 
-        return new PhpType().add("#" + this.getKey() + refSignature + TRIM_KEY + repositorySignature);
+        return new PhpType().add(signature);
     }
 
     @Override
@@ -155,8 +150,10 @@ public Collection<? extends PhpNamedElement> getBySignature(String expression, S
 
         String name = method.getName();
         if(name.equals("findAll") || name.equals("findBy")) {
-            method.getType().add(phpClass.getFQN() + "[]");
-            return phpNamedElementCollections;
+            Method m = new MethodImpl(method.getNode());
+            m.getType().add(phpClass.getFQN() + "[]");
+
+            return PhpTypeProviderUtil.mergeSignatureResults(phpNamedElementCollections, m);
         }
 
         return PhpTypeProviderUtil.mergeSignatureResults(phpNamedElementCollections, phpClass);