Groovy type assignability
[idea/community.git] / plugins / groovy / src / org / jetbrains / plugins / groovy / lang / psi / impl / types / GrCodeReferenceElementImpl.java
index 6c1d4ba60b90256f46ed2e12d3f83d3a5b441fda..6b0016536bcba69089c5476c8a0e09133aa2a150 100644 (file)
 
 package org.jetbrains.plugins.groovy.lang.psi.impl.types;
 
-import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.codeInsight.lookup.LookupElementFactory;
-import com.intellij.codeInsight.lookup.MutableLookupElement;
 import com.intellij.lang.ASTNode;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.source.resolve.ResolveCache;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.ArrayUtil;
+import com.intellij.util.Consumer;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil;
@@ -122,6 +120,10 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl implement
   }
 
   private ReferenceKind getKind(boolean forCompletion) {
+    if (isClassReferenceForNew()) {
+      return CLASS_OR_PACKAGE;
+    }
+
     PsiElement parent = getParent();
     if (parent instanceof GrCodeReferenceElement) {
       ReferenceKind parentKind = ((GrCodeReferenceElementImpl) parent).getKind(forCompletion);
@@ -197,11 +199,7 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl implement
 
   @NotNull
   public Object[] getVariants() {
-    if (isClassReferenceForNew()) {
-      return getVariantsForNewExpression();
-    }
-
-    return getVariantsImpl(getKind(true));
+    return ArrayUtil.EMPTY_OBJECT_ARRAY;
   }
 
   private boolean isClassReferenceForNew() {
@@ -210,30 +208,7 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl implement
     return parent instanceof GrNewExpression;
   }
 
-  private Object[] getVariantsForNewExpression() {
-    final Object[] classVariants = getVariantsImpl(CLASS_OR_PACKAGE);
-    List<Object> result = new ArrayList<Object>();
-    for (Object variant : classVariants) {
-      if (variant instanceof PsiClass) {
-        final PsiClass clazz = (PsiClass) variant;
-        final MutableLookupElement<PsiClass> lookupElement = LookupElementFactory.getInstance().createLookupElement(clazz);
-        result.add(GroovyCompletionUtil.setTailTypeForConstructor(clazz, lookupElement));
-      } else if (variant instanceof LookupElement) {
-        final LookupElement lookupElement = (LookupElement) variant;
-        final Object obj = lookupElement.getObject();
-        if (obj instanceof PsiClass) {
-          result.add(GroovyCompletionUtil.setTailTypeForConstructor((PsiClass) obj, lookupElement));
-        } else {
-          result.add(lookupElement);
-        }
-      } else {
-        result.add(variant);
-      }
-    }
-    return ArrayUtil.toObjectArray(result);
-  }
-
-  private Object[] getVariantsImpl(ReferenceKind kind) {
+  private void processVariantsImpl(ReferenceKind kind, Consumer<Object> consumer) {
     switch (kind) {
       case STATIC_MEMBER_FQ: {
         final GrCodeReferenceElement qualifier = getQualifier();
@@ -241,21 +216,19 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl implement
           final PsiElement resolve = qualifier.resolve();
           if (resolve instanceof PsiClass) {
             final PsiClass clazz = (PsiClass) resolve;
-            List<PsiElement> result = new ArrayList<PsiElement>();
 
             for (PsiField field : clazz.getFields()) {
               if (field.hasModifierProperty(PsiModifier.STATIC)) {
-                result.add(field);
+                consumer.consume(field);
               }
             }
 
             for (PsiMethod method : clazz.getMethods()) {
               if (method.hasModifierProperty(PsiModifier.STATIC)) {
-                result.add(method);
+                consumer.consume(method);
               }
             }
-
-            return result.toArray(new PsiElement[result.size()]);
+            return;
           }
         }
       }
@@ -271,17 +244,26 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl implement
         if (parentPackage != null) {
           final GlobalSearchScope scope = getResolveScope();
           if (kind == PACKAGE_FQ) {
-            return parentPackage.getSubPackages(scope);
+            for (PsiPackage aPackage : parentPackage.getSubPackages(scope)) {
+              consumer.consume(aPackage);
+            }
+            return;
           } else {
             if (kind == CLASS_FQ) {
-              return parentPackage.getClasses(scope);
+              for (PsiClass aClass : parentPackage.getClasses(scope)) {
+                consumer.consume(aClass);
+              }
+              return;
             } else {
               final PsiPackage[] subpackages = parentPackage.getSubPackages(scope);
               final PsiClass[] classes = parentPackage.getClasses(scope);
-              PsiElement[] result = new PsiElement[subpackages.length + classes.length];
-              System.arraycopy(subpackages, 0, result, 0, subpackages.length);
-              System.arraycopy(classes, 0, result, subpackages.length, classes.length);
-              return result;
+              for (PsiPackage aPackage : subpackages) {
+                consumer.consume(aPackage);
+              }
+              for (PsiClass aClass : classes) {
+                consumer.consume(aClass);
+              }
+              return;
             }
           }
         }
@@ -296,21 +278,31 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl implement
           if (qualifierResolved instanceof PsiPackage) {
             PsiPackage aPackage = (PsiPackage) qualifierResolved;
             PsiClass[] classes = aPackage.getClasses(getResolveScope());
-            if (kind == CLASS) return classes;
+
+            for (PsiClass aClass : classes) {
+              consumer.consume(aClass);
+            }
+            if (kind == CLASS) return;
+
             PsiPackage[] subpackages = aPackage.getSubPackages();
-            return ArrayUtil.mergeArrays(classes, subpackages, Object.class);
+            for (PsiPackage subpackage : subpackages) {
+              consumer.consume(subpackage);
+            }
           } else if (qualifierResolved instanceof PsiClass) {
-            return ((PsiClass) qualifierResolved).getInnerClasses();
+            for (PsiClass aClass : ((PsiClass)qualifierResolved).getInnerClasses()) {
+              consumer.consume(aClass);
+            }
           }
         } else {
-          ResolverProcessor processor = CompletionProcessor.createClassCompletionProcessor(this);
-          ResolveUtil.treeWalkUp(this, processor, false);
-          return GroovyCompletionUtil.getCompletionVariants(processor.getCandidates());
+          ResolverProcessor classProcessor = CompletionProcessor.createClassCompletionProcessor(this);
+          ResolveUtil.treeWalkUp(this, classProcessor, false);
+
+          for (Object o : GroovyCompletionUtil.getCompletionVariants(classProcessor.getCandidates())) {
+            consumer.consume(o);
+          }
         }
       }
     }
-
-    return ArrayUtil.EMPTY_OBJECT_ARRAY;
   }
 
   public boolean isSoft() {
@@ -489,4 +481,8 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl implement
 
     return (GroovyResolveResult[])results;
   }
+
+  public void processVariants(Consumer<Object> consumer) {
+    processVariantsImpl(getKind(true), consumer);
+  }
 }