IDEA-59955 IDEA does not infert the 'def' type in Groovy if we use factory methods...
authorMaxim Medvedev <maxim.medvedev@jetbrains.com>
Wed, 20 Oct 2010 12:50:37 +0000 (16:50 +0400)
committerMaxim Medvedev <maxim.medvedev@jetbrains.com>
Wed, 20 Oct 2010 12:56:32 +0000 (16:56 +0400)
java/openapi/src/com/intellij/psi/GenericsUtil.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java
plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java
plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.java
plugins/groovy/testdata/resolve/inference/rawTypeInReturnExpression/A.groovy [new file with mode: 0644]

index 585f9692aec96dd76c2b54cda9f0fe2ccfb71bf5..412e11a52c8501c3c6c00e2647cac82097ca8098 100644 (file)
@@ -15,8 +15,8 @@
  */
 package com.intellij.psi;
 
-import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Pair;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.InheritanceUtil;
 import com.intellij.psi.util.PsiUtil;
index e4c0aa9a54313d5caeb966882d5fcc99b04628cb..88c645aacb77ec34e8266405581339d1f588e601 100644 (file)
@@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions;
 
 import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiSubstitutorImpl;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.InheritanceUtil;
@@ -487,4 +488,13 @@ public class TypesUtil {
   public static boolean typeEqualsToText(@NotNull PsiType type, @NotNull String text) {
     return text.endsWith(type.getPresentableText()) && text.equals(type.getCanonicalText());
   }
+
+  public static PsiSubstitutor composeSubstitutors(PsiSubstitutor s1, PsiSubstitutor s2) {
+    final Map<PsiTypeParameter, PsiType> map = s1.getSubstitutionMap();
+    Map<PsiTypeParameter, PsiType> result = new com.intellij.util.containers.hash.HashMap<PsiTypeParameter, PsiType>(map.size());
+    for (PsiTypeParameter parameter : map.keySet()) {
+      result.put(parameter, s2.substitute(map.get(parameter)));
+    }
+    return PsiSubstitutorImpl.createSubstitutor(result);
+  }
 }
index e00a97424b9c87f0368f83a72a3506bb94207dd7..a5c0ff4b734bff26505ebe63707ce82a7cefb047 100644 (file)
  */
 package org.jetbrains.plugins.groovy.refactoring.changeSignature;
 
-import com.intellij.psi.*;
-import com.intellij.psi.impl.PsiSubstitutorImpl;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiSubstitutor;
 import com.intellij.psi.util.InheritanceUtil;
 import com.intellij.psi.util.MethodSignature;
 import com.intellij.psi.util.MethodSignatureUtil;
 import com.intellij.psi.util.TypeConversionUtil;
 import com.intellij.refactoring.changeSignature.PossiblyIncorrectUsage;
 import com.intellij.usageView.UsageInfo;
-import com.intellij.util.containers.hash.HashMap;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
@@ -33,11 +34,10 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethod
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
 import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
 import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
 
-import java.util.Map;
-
 /**
  * @author Maxim.Medvedev
  */
@@ -73,7 +73,7 @@ public class GrMethodCallUsageInfo extends UsageInfo implements PossiblyIncorrec
           final MethodSignature methodSignature = resolved.getSignature(PsiSubstitutor.EMPTY);
           final PsiSubstitutor superMethodSignatureSubstitutor =
             MethodSignatureUtil.getSuperMethodSignatureSubstitutor(methodSignature, superMethodSignature);
-          mySubstitutor = composeSubstitutors(superMethodSignatureSubstitutor, mySubstitutor);
+          mySubstitutor = TypesUtil.composeSubstitutors(superMethodSignatureSubstitutor, mySubstitutor);
         }
       }
     }
@@ -90,15 +90,6 @@ public class GrMethodCallUsageInfo extends UsageInfo implements PossiblyIncorrec
     }
   }
 
-  private static PsiSubstitutor composeSubstitutors(PsiSubstitutor s1, PsiSubstitutor s2) {
-    final Map<PsiTypeParameter, PsiType> map = s1.getSubstitutionMap();
-    Map<PsiTypeParameter, PsiType> result = new HashMap<PsiTypeParameter, PsiType>(map.size());
-    for (PsiTypeParameter parameter : map.keySet()) {
-      result.put(parameter, s2.substitute(map.get(parameter)));
-    }
-    return PsiSubstitutorImpl.createSubstitutor(result);
-  }
-
   @Nullable
   public static GroovyResolveResult resolveMethod(final PsiElement ref) {
     if (ref instanceof GrEnumConstant) return ((GrEnumConstant)ref).resolveConstructorGenerics();
index 6a6fd3b290235d4baeed4e357c3bbcb32ae1b18c..76f913c140d0f86b66a15cf64e43418f451d0355 100644 (file)
@@ -138,4 +138,8 @@ public class TypeInferenceTest extends GroovyResolveTestCase {
     GrReferenceExpression refExpr = (GrReferenceExpression)configureByFile("parameterWithBuiltinType/A.groovy");
     assertEquals("java.lang.Integer", refExpr.getType().getCanonicalText());
   }
+
+  public void testRawTypeInReturnExpression() {
+    assertNotNull(resolve("A.groovy"));
+  }
 }
diff --git a/plugins/groovy/testdata/resolve/inference/rawTypeInReturnExpression/A.groovy b/plugins/groovy/testdata/resolve/inference/rawTypeInReturnExpression/A.groovy
new file mode 100644 (file)
index 0000000..c650108
--- /dev/null
@@ -0,0 +1,14 @@
+class MissingInferenceTest {
+  Map<String, Map<Integer, List<Date>>> factoryMethod() { [:]}
+
+  def myMethod() {
+    Map<String, Map<Integer, List<Date>>> dataTyped = [:]
+    def dataInferred = new HashMap<String, Map<Integer, List<Date>>>()
+    def dataNotInferred = factoryMethod()
+
+    println dataTyped      ['foo'][5][2].time()
+    println dataInferred   ['foo'][5][2].time()
+    println dataNotInferred['foo'][5][2].tim<ref>e() // no completion, highlighted as dynamic
+  }
+}
+