use old GroovyExpectedTypesUtil for smart completion
authorMaxim Medvedev <maxim.medvedev@jetbrains.com>
Thu, 4 Feb 2010 16:13:08 +0000 (19:13 +0300)
committerMaxim Medvedev <maxim.medvedev@jetbrains.com>
Thu, 4 Feb 2010 16:13:08 +0000 (19:13 +0300)
16 files changed:
plugins/groovy/src/META-INF/plugin.xml
plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFromUsageFix.java
plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateLocalVariableFromUsageFix.java
plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java
plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/ui/DynamicMethodDialog.java
plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/ui/DynamicPropertyDialog.java
plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyExpectedTypesProvider.java [deleted file]
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java [moved from plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesUtil.java with 68% similarity]
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/SubtypeConstraint.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/SupertypeConstraint.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/TypeConstraint.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/TypeEquals.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java
plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCompletionTest.java
plugins/groovy/testdata/groovy/completion/ReturnStatement.groovy [new file with mode: 0644]

index 4e5e4a10e4754c8c055ef36437619a22e6bf6c84..9a02673f9b706e7b37901d759781e353eb2ce428 100644 (file)
@@ -70,7 +70,6 @@
     <constantExpressionEvaluator language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.psi.util.GroovyConstantExpressionEvaluator"/>
     <annotationSupport language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GroovyAnnotationSupport"/>
 
-    <!--<expectedTypesProvider implementation="org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider"/>-->
     <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
     <fileTypeFactory implementation="org.jetbrains.plugins.groovy.GroovyFileTypeLoader"/>
 
     <projectService serviceInterface="org.jetbrains.plugins.groovy.codeInspection.GroovyImportsTracker"
                     serviceImplementation="org.jetbrains.plugins.groovy.codeInspection.GroovyImportsTracker"/>
 
-    <projectService serviceInterface="org.jetbrains.plugins.groovy.codeInsight.GroovyExpectedTypesProvider"
-                    serviceImplementation="org.jetbrains.plugins.groovy.codeInsight.GroovyExpectedTypesProvider"/>
-
-
     <psi.referenceContributor implementation="org.jetbrains.plugins.groovy.gant.GantReferenceContributor"/>
     <psi.referenceContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.providers.GroovyReferenceContributor"/>
 
index 5c06006dbaab053f255a79ab8a5972606217adf8..808c25838b2dc0f5707b74583ec744ad3613db53 100644 (file)
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.GroovyBundle;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner;
-import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesUtil;
+import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider;
 import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
 import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
 
@@ -62,7 +62,7 @@ public class CreateFieldFromUsageFix extends CreateFieldFix {
   }
 
   protected TypeConstraint[] calculateTypeConstrains() {
-    return GroovyExpectedTypesUtil.calculateTypeConstraints(myRefExpression);
+    return GroovyExpectedTypesProvider.calculateTypeConstraints(myRefExpression);
 
   }
 }
index c54b2b8ca5db1557a06dc926ff37961186a8272e..1e5255a701e8f0e6f76d7f90592a608a02097148 100644 (file)
@@ -39,7 +39,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaratio
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
 import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner;
-import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesUtil;
+import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider;
 import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
 
 /**
@@ -85,7 +85,7 @@ public class CreateLocalVariableFromUsageFix implements IntentionAction {
     int offset = myRefExpression.getTextRange().getStartOffset();
     GrStatement anchor = findAnchor(file, offset);
 
-    TypeConstraint[] constraints = GroovyExpectedTypesUtil.calculateTypeConstraints(myRefExpression);
+    TypeConstraint[] constraints = GroovyExpectedTypesProvider.calculateTypeConstraints(myRefExpression);
     if (anchor.equals(myRefExpression)) {
       decl = myRefExpression.replaceWithStatement(decl);
     } else {
index 41f44fb1ba7975f250bc5d8c0ef5097066a33c79..c14efd35f9e5489b2fdca5d5151579dafb031651 100644 (file)
@@ -33,7 +33,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrRefere
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
-import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesUtil;
+import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider;
 import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint;
 import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
@@ -83,7 +83,7 @@ public class CreateMethodFromUsageFix implements IntentionAction {
     methodBuffer.append(") {\n}");
     GrMethod method = GroovyPsiElementFactory.getInstance(project).createMethodFromText(methodBuffer.toString());
     GrMemberOwner owner = myTargetClass;
-    TypeConstraint[] constraints = GroovyExpectedTypesUtil.calculateTypeConstraints((GrExpression) myRefExpression.getParent());
+    TypeConstraint[] constraints = GroovyExpectedTypesProvider.calculateTypeConstraints((GrExpression) myRefExpression.getParent());
     PsiElement parent = myTargetClass instanceof GrTypeDefinition ? ((GrTypeDefinition)myTargetClass).getBody() : ((GroovyScriptClass) myTargetClass).getContainingFile();
     if (PsiTreeUtil.isAncestor(parent, myRefExpression, false)) {
       PsiElement prevParent = PsiTreeUtil.findPrevParent(parent, myRefExpression);
index 1275eda5cd648cd97bcd1ba84ae5243a1d1c633f..0054c8f3f08ca8a262d7620d757e4e7a944c4999 100644 (file)
@@ -26,7 +26,7 @@ import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.MyPair;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
-import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesUtil;
+import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider;
 
 import javax.swing.*;
 import javax.swing.event.CellEditorListener;
@@ -46,7 +46,7 @@ public class DynamicMethodDialog extends DynamicDialog {
   private final GrReferenceExpression myReferenceExpression;
 
   public DynamicMethodDialog(GrReferenceExpression referenceExpression) {
-    super(referenceExpression, QuickfixUtil.createSettings(referenceExpression), GroovyExpectedTypesUtil.calculateTypeConstraints((GrExpression)referenceExpression.getParent()));
+    super(referenceExpression, QuickfixUtil.createSettings(referenceExpression), GroovyExpectedTypesProvider.calculateTypeConstraints((GrExpression)referenceExpression.getParent()));
     myReferenceExpression = referenceExpression;
     assert getSettings().isMethod();
 
index 3bd0191d323d9efcd8d12b48f29d2ed9c61e0d91..98c3dd49e7defda435819e54e199aec177b4f250 100644 (file)
@@ -20,7 +20,7 @@ import org.jetbrains.plugins.groovy.GroovyBundle;
 import org.jetbrains.plugins.groovy.annotator.intentions.QuickfixUtil;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
-import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesUtil;
+import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider;
 import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint;
 
 /**
@@ -32,7 +32,7 @@ public class DynamicPropertyDialog extends DynamicDialog {
   private final GrArgumentLabel myLabel;
 
   public DynamicPropertyDialog(GrReferenceExpression referenceExpression) {
-    super(referenceExpression, QuickfixUtil.createSettings(referenceExpression), GroovyExpectedTypesUtil.calculateTypeConstraints(referenceExpression));
+    super(referenceExpression, QuickfixUtil.createSettings(referenceExpression), GroovyExpectedTypesProvider.calculateTypeConstraints(referenceExpression));
     myReferenceExpression = referenceExpression;
     myLabel = null;
     setTitle(GroovyBundle.message("add.dynamic.property", referenceExpression.getReferenceName()));
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyExpectedTypesProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyExpectedTypesProvider.java
deleted file mode 100644 (file)
index 0d41ab0..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright 2000-2010 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jetbrains.plugins.groovy.codeInsight;
-
-import com.intellij.codeInsight.*;
-import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.codeStyle.JavaCodeStyleManager;
-import com.intellij.psi.codeStyle.VariableKind;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.PsiShortNamesCache;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.containers.hash.HashSet;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
-import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
-import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrForStatement;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrForClause;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrTraditionalForClause;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
-
-import java.util.Set;
-
-/**
- * @author Maxim.Medvedev
- */
-public class GroovyExpectedTypesProvider {
-  private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.codeInsight.GroovyExpectedTypesProvider");
-
-  private static final ExpectedTypesProvider.ExpectedClassProvider OUR_GLOBAL_SCOPE_CLASS_PROVIDER = new ExpectedTypesProvider.ExpectedClassProvider() {
-    public PsiField[] findDeclaredFields(final PsiManager manager, String name) {
-      final PsiShortNamesCache cache = JavaPsiFacade.getInstance(manager.getProject()).getShortNamesCache();
-      GlobalSearchScope scope = GlobalSearchScope.allScope(manager.getProject());
-      return cache.getFieldsByName(name, scope);
-    }
-
-    public PsiMethod[] findDeclaredMethods(final PsiManager manager, String name) {
-      final PsiShortNamesCache cache = JavaPsiFacade.getInstance(manager.getProject()).getShortNamesCache();
-      GlobalSearchScope scope = GlobalSearchScope.allScope(manager.getProject());
-      return cache.getMethodsByName(name, scope);
-    }
-  };
-
-  public GroovyExpectedTypesProvider() {
-  }
-
-  public static GroovyExpectedTypesProvider getInstance(Project project) {
-    return ServiceManager.getService(project, GroovyExpectedTypesProvider.class);
-  }
-
-  private static ExpectedTypeInfoImpl createInfoImpl(@NotNull PsiType type, int kind, PsiType defaultType, TailType tailType) {
-    int dims = 0;
-    while (type instanceof PsiArrayType) {
-      type = ((PsiArrayType)type).getComponentType();
-      LOG.assertTrue(defaultType instanceof PsiArrayType);
-      defaultType = ((PsiArrayType)defaultType).getComponentType();
-      dims++;
-    }
-    return new ExpectedTypeInfoImpl(type, kind, dims, defaultType, tailType);
-  }
-
-
-  @Nullable
-  public ExpectedTypeInfo[] getExpectedTypes(GrExpression expr,
-                                             boolean forCompletion,
-                                             final boolean voidable) {
-    return getExpectedTypes(expr, forCompletion, OUR_GLOBAL_SCOPE_CLASS_PROVIDER, voidable);
-  }
-
-  @Nullable
-  public ExpectedTypeInfo[] getExpectedTypes(GrExpression expr,
-                                             boolean forCompletion,
-                                             ExpectedTypesProvider.ExpectedClassProvider classProvider,
-                                             final boolean voidable) {
-    if (expr == null) return null;
-    PsiElement parent = expr.getParent();
-    while (parent instanceof GrParenthesizedExpression) {
-      expr = (GrExpression)parent;
-      parent = parent.getParent();
-    }
-    MyParentVisitor visitor = new MyParentVisitor(expr, forCompletion, classProvider, voidable);
-    ((GroovyPsiElement)parent).accept(visitor);
-    return visitor.getResult();
-  }
-
-
-  private static class MyParentVisitor extends GroovyElementVisitor {
-    private ExpectedTypeInfo[] myResult = ExpectedTypeInfo.EMPTY_ARRAY;
-
-    private GrExpression myExpr;
-    private final boolean myForCompletion;
-    private final ExpectedTypesProvider.ExpectedClassProvider myClassProvider;
-    private final boolean myVoidable;
-
-    private MyParentVisitor(GrExpression expr,
-                            boolean forCompletion,
-                            ExpectedTypesProvider.ExpectedClassProvider classProvider,
-                            boolean voidable) {
-      myExpr = expr;
-      myForCompletion = forCompletion;
-      myClassProvider = classProvider;
-      myVoidable = voidable;
-    }
-
-    public ExpectedTypeInfo[] getResult() {
-      return myResult;
-    }
-
-    @Override
-    public void visitAssignmentExpression(GrAssignmentExpression assignment) {
-      if (myExpr == assignment.getRValue()) {
-        GrExpression lExpr = assignment.getLValue();
-        PsiType type = lExpr.getType();
-        if (type != null) {
-          TailType tailType = getAssignmentRValueTailType(assignment);
-          ExpectedTypeInfoImpl info = createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, tailType);
-          if (lExpr instanceof GrReferenceExpression) {
-            PsiElement refElement = ((GrReferenceExpression)lExpr).resolve();
-            if (refElement instanceof GrVariable) {
-              info.expectedName = getPropertyName((GrVariable)refElement);
-            }
-          }
-          myResult = new ExpectedTypeInfo[]{info};
-        }
-        else {
-          myResult = ExpectedTypeInfo.EMPTY_ARRAY;
-        }
-
-      }
-      else {
-        if (myForCompletion) {
-          myExpr = (GrExpression)myExpr.getParent();
-          ((GroovyPsiElement)assignment.getParent()).accept(this);
-          return;
-        }
-
-        GrExpression rExpr = assignment.getRValue();
-        if (rExpr != null) {
-          PsiType type = rExpr.getType();
-          if (type != null) {
-            if (type instanceof PsiClassType) {
-              final PsiClass resolved = ((PsiClassType)type).resolve();
-              if (resolved instanceof PsiAnonymousClass) {
-                type = ((PsiAnonymousClass)resolved).getBaseClassType();
-              }
-            }
-            ExpectedTypeInfoImpl info = createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUPERTYPE, type,
-                                                       TailType.NONE);
-            myResult = new ExpectedTypeInfo[]{info};
-            return;
-          }
-        }
-        myResult = ExpectedTypeInfo.EMPTY_ARRAY;
-      }
-    }
-
-    @Override
-    public void visitArgumentList(GrArgumentList list) {
-      final PsiElement parent = list.getParent();
-
-      GroovyResolveResult[] results = null;
-      if (parent instanceof GrMethodCallExpression) {
-        final GrExpression expression = ((GrMethodCallExpression)parent).getInvokedExpression();
-        if (expression instanceof GrReferenceExpression) {
-          results = ((GrReferenceExpression)expression).multiResolve(false);
-        }
-      }
-      else if (parent instanceof GrApplicationStatement) {
-        final GrExpression expression = ((GrApplicationStatement)parent).getFunExpression();
-        if (expression instanceof GrReferenceExpression) {
-          results = ((GrReferenceExpression)expression).multiResolve(false);
-        }
-      }
-      else if (parent instanceof GrConstructorCall) {
-        results = ((GrConstructorCall)parent).multiResolveConstructor();
-      }
-
-      if (results == null || results.length == 0) return;
-
-      final int argumentIndex = list.getExpressionArgumentIndex(myExpr);
-      assert argumentIndex != -1;
-
-      Set<ExpectedTypeInfo> infos = new HashSet<ExpectedTypeInfo>();
-      for (GroovyResolveResult result : results) {
-        final PsiElement element = result.getElement();
-        if (!(element instanceof PsiMethod)) continue;
-        final PsiParameter[] parameters = ((PsiMethod)element).getParameterList().getParameters();
-        if (parameters.length < argumentIndex) continue;
-        final PsiParameter parameter = parameters[argumentIndex];
-        final PsiType type = parameter.getType();
-        final TailType tailType = getMethodArgumentTailType(myExpr, argumentIndex, (PsiMethod)element, result.getSubstitutor(), parameters);
-        infos.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, tailType));
-      }
-      myResult = infos.toArray(new ExpectedTypeInfo[infos.size()]);
-    }
-
-    private static TailType getAssignmentRValueTailType(GrAssignmentExpression assignment) {
-      if (assignment.getParent() instanceof GrExpression) {
-        if (!(assignment.getParent().getParent() instanceof GrForStatement)) {
-          return TailType.SEMICOLON;
-        }
-
-        GrForStatement forStatement = (GrForStatement)assignment.getParent().getParent();
-        final GrForClause forClause = forStatement.getClause();
-        if (forClause instanceof GrTraditionalForClause) {
-          if (ArrayUtil.find(((GrTraditionalForClause)forClause).getUpdate(), assignment.getParent()) != -1) {
-            return TailType.SEMICOLON;
-          }
-        }
-      }
-      return TailType.NONE;
-    }
-
-    @Nullable
-    private static String getPropertyName(GrVariable variable) {
-      final String name = variable.getName();
-      if (name == null) return null;
-      JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(variable.getProject());
-      VariableKind variableKind = codeStyleManager.getVariableKind(variable);
-      return codeStyleManager.variableNameToPropertyName(name, variableKind);
-    }
-
-    private TailType getMethodArgumentTailType(final GrExpression argument, final int index, final PsiMethod method, final PsiSubstitutor substitutor,
-                                               final PsiParameter[] parms) {
-      if (index >= parms.length) {
-        return TailType.NONE;
-      }
-      if (index == parms.length - 1) {
-        //myTailType = CompletionUtil.NONE_TAIL;
-        final PsiElement call = argument.getParent().getParent();
-
-        PsiType returnType = method.getReturnType();
-        if (returnType != null) returnType = substitutor.substitute(returnType);
-        return (PsiType.VOID.equals(returnType) || returnType == null) && call.getParent() instanceof PsiStatement
-               ? TailTypes.CALL_RPARENTH_SEMICOLON
-               : TailTypes.CALL_RPARENTH;
-      }
-      return TailType.COMMA;
-    }
-  }
-}
index c52e4b5bb0eed81d04fa58f8d29d50bc21451d7d..cd1871292fdb67d221f7b94471a321f342a7f47c 100644 (file)
@@ -15,7 +15,6 @@
  */
 package org.jetbrains.plugins.groovy.lang.completion;
 
-import com.intellij.codeInsight.ExpectedTypeInfo;
 import com.intellij.codeInsight.completion.*;
 import com.intellij.codeInsight.lookup.LookupElement;
 import com.intellij.codeInsight.lookup.LookupItemUtil;
@@ -34,12 +33,12 @@ import gnu.trove.THashSet;
 import gnu.trove.TObjectHashingStrategy;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.groovy.codeInsight.GroovyExpectedTypesProvider;
 import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
-import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
+import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider;
+import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
 
 import java.util.Arrays;
 import java.util.Set;
@@ -51,14 +50,14 @@ import static com.intellij.patterns.PlatformPatterns.psiElement;
  */
 public class GroovySmartCompletionContributor extends CompletionContributor {
   private static final ElementPattern<PsiElement> INSIDE_EXPRESSION = psiElement().withParent(GrExpression.class);
-  private static final TObjectHashingStrategy<ExpectedTypeInfo> EXPECTED_TYPE_INFO_STRATEGY =
-    new TObjectHashingStrategy<ExpectedTypeInfo>() {
-      public int computeHashCode(final ExpectedTypeInfo object) {
+  private static final TObjectHashingStrategy<TypeConstraint> EXPECTED_TYPE_INFO_STRATEGY =
+    new TObjectHashingStrategy<TypeConstraint>() {
+      public int computeHashCode(final TypeConstraint object) {
         return object.getType().hashCode();
       }
 
-      public boolean equals(final ExpectedTypeInfo o1, final ExpectedTypeInfo o2) {
-        return o1.getType().equals(o2.getType());
+      public boolean equals(final TypeConstraint o1, final TypeConstraint o2) {
+        return o1.getClass().equals(o2.getClass()) && o1.getType().equals(o2.getType());
       }
     };
 
@@ -71,15 +70,15 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
         final PsiElement position = params.getPosition();
         if (position.getParent() instanceof GrLiteral) return;
 
-        final THashSet<ExpectedTypeInfo> _infos = new THashSet<ExpectedTypeInfo>();
+        final THashSet<TypeConstraint> _infos = new THashSet<TypeConstraint>();
         ApplicationManager.getApplication().runReadAction(new Runnable() {
           public void run() {
             _infos.addAll(Arrays.asList(getExpectedTypes(params)));
           }
         });
-        final Set<ExpectedTypeInfo> infos = ApplicationManager.getApplication().runReadAction(new Computable<Set<ExpectedTypeInfo>>() {
-          public Set<ExpectedTypeInfo> compute() {
-            return new THashSet<ExpectedTypeInfo>(_infos, EXPECTED_TYPE_INFO_STRATEGY);
+        final Set<TypeConstraint> infos = ApplicationManager.getApplication().runReadAction(new Computable<Set<TypeConstraint>>() {
+          public Set<TypeConstraint> compute() {
+            return new THashSet<TypeConstraint>(_infos, EXPECTED_TYPE_INFO_STRATEGY);
           }
         });
 
@@ -99,8 +98,8 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
                 }
               }
               if (type == null) return;
-              for (ExpectedTypeInfo info : infos) {
-                if (TypesUtil.isAssignableByMethodCallConversion(info.getType(), type, position.getManager(), GlobalSearchScope.allScope(position.getProject()))) {
+              for (TypeConstraint info : infos) {
+                if (info.satisfied(type, position.getManager(), GlobalSearchScope.allScope(position.getProject()))) {
                   final LookupElement lookupElement = LookupItemUtil.objectToLookupItem(variant);
                   result.addElement(lookupElement);
                   break;
@@ -115,12 +114,11 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
   }
 
   @Nullable
-  public static ExpectedTypeInfo[] getExpectedTypes(CompletionParameters params) {
+  public static TypeConstraint[] getExpectedTypes(CompletionParameters params) {
     final PsiElement position = params.getPosition();
     final GrExpression expression = PsiTreeUtil.getParentOfType(position, GrExpression.class);
     if (expression != null) {
-      return GroovyExpectedTypesProvider.getInstance(position.getProject())
-        .getExpectedTypes(expression, true, params.getCompletionType() == CompletionType.SMART);
+      return GroovyExpectedTypesProvider.calculateTypeConstraints(expression);
     }
     return null;
   }
similarity index 68%
rename from plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesUtil.java
rename to plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java
index 923a3fff3c41447e481892f3809a947050ba04f3..c590e65b1ea69e808d08b92044bd351f6b949da7 100644 (file)
  */
 package org.jetbrains.plugins.groovy.lang.psi.expectedTypes;
 
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiType;
+import com.intellij.psi.*;
 import com.intellij.psi.util.PsiTreeUtil;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
 import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrWhileStatement;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrThrowStatement;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrTraditionalForClause;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
@@ -44,10 +43,13 @@ import java.util.List;
 /**
  * @author ven
  */
-public class GroovyExpectedTypesUtil {
+public class GroovyExpectedTypesProvider {
+  private GroovyExpectedTypesProvider() {
+  }
+
   public static TypeConstraint[] calculateTypeConstraints(GrExpression expression) {
     MyCalculator calculator = new MyCalculator(expression);
-    ((GroovyPsiElement) expression.getParent()).accept(calculator);
+    ((GroovyPsiElement)expression.getParent()).accept(calculator);
     return calculator.getResult();
   }
 
@@ -58,117 +60,101 @@ public class GroovyExpectedTypesUtil {
 
     public MyCalculator(GrExpression expression) {
       myExpression = expression;
-    }
-
-    public void visitElement(GroovyPsiElement element) {
-      makeDefault();
+      myResult = new TypeConstraint[]{SubtypeConstraint.create("java.lang.Object", myExpression)};
     }
 
     public void visitReturnStatement(GrReturnStatement returnStatement) {
       GrParametersOwner parent = PsiTreeUtil.getParentOfType(returnStatement, GrMethod.class, GrClosableBlock.class);
       if (parent instanceof GrMethod) {
-        GrTypeElement typeElement = ((GrMethod) parent).getReturnTypeElementGroovy();
+        GrTypeElement typeElement = ((GrMethod)parent).getReturnTypeElementGroovy();
         if (typeElement != null) {
           PsiType type = typeElement.getType();
-          myResult = new TypeConstraint[] {SubtypeConstraint.create(type)};
-          return;
+          myResult = new TypeConstraint[]{SubtypeConstraint.create(type)};
         }
       }
-      makeDefault();
     }
 
     public void visitVariable(GrVariable variable) {
       if (myExpression.equals(variable.getInitializerGroovy())) {
         PsiType type = variable.getDeclaredType();
         if (type != null) {
-          myResult = new TypeConstraint[] {new SubtypeConstraint(type, type)};
-          return;
+          myResult = new TypeConstraint[]{new SubtypeConstraint(type, type)};
         }
       }
-      makeDefault();
     }
 
     public void visitMethodCallExpression(GrMethodCallExpression methodCall) {
       if (myExpression.equals(methodCall.getInvokedExpression())) {
         myResult = new TypeConstraint[]{SubtypeConstraint.create("groovy.lang.Closure", methodCall)};
-      } else {
-        makeDefault();
       }
     }
 
     public void visitIfStatement(GrIfStatement ifStatement) {
       if (myExpression.equals(ifStatement.getCondition())) {
-        myResult = new TypeConstraint[] {new SubtypeConstraint(TypesUtil.getJavaLangObject(ifStatement), PsiType.BOOLEAN)};
-      } else makeDefault();
+        myResult = new TypeConstraint[]{new SubtypeConstraint(TypesUtil.getJavaLangObject(ifStatement), PsiType.BOOLEAN)};
+      }
     }
 
     public void visitWhileStatement(GrWhileStatement whileStatement) {
       if (myExpression.equals(whileStatement.getCondition())) {
-        myResult = new TypeConstraint[] {new SubtypeConstraint(TypesUtil.getJavaLangObject(whileStatement), PsiType.BOOLEAN)};
-      } else makeDefault();
+        myResult = new TypeConstraint[]{new SubtypeConstraint(TypesUtil.getJavaLangObject(whileStatement), PsiType.BOOLEAN)};
+      }
     }
 
     public void visitTraditionalForClause(GrTraditionalForClause forClause) {
       if (myExpression.equals(forClause.getCondition())) {
-        myResult = new TypeConstraint[] {new SubtypeConstraint(TypesUtil.getJavaLangObject(forClause), PsiType.BOOLEAN)};
-      } else makeDefault();
+        myResult = new TypeConstraint[]{new SubtypeConstraint(TypesUtil.getJavaLangObject(forClause), PsiType.BOOLEAN)};
+      }
     }
 
     public void visitArgumentList(GrArgumentList list) {
       PsiElement parent = list.getParent();
       List<TypeConstraint> constraints = new ArrayList<TypeConstraint>();
       if (parent instanceof GrCallExpression) {
-        GroovyResolveResult[] variants = ((GrCallExpression) parent).getMethodVariants();
-        int idx = getIndex(list);
+        GroovyResolveResult[] variants = ((GrCallExpression)parent).getMethodVariants();
+        int idx = list.getExpressionArgumentIndex(myExpression);
         for (GroovyResolveResult variant : variants) {
           PsiElement element = variant.getElement();
+          PsiParameter[] parameters = null;
           if (element instanceof GrParametersOwner) {
-            GrParameter[] parameters = ((GrParametersOwner) element).getParameters();
-            if (parameters.length <= idx) continue;
-            PsiType parameterType = variant.getSubstitutor().substitute(parameters[idx].getType());
-            constraints.add(SubtypeConstraint.create(parameterType));
+            parameters = ((GrParametersOwner)element).getParameters();
           }
+          else if (element instanceof PsiMethod) {
+            parameters = ((PsiMethod)element).getParameterList().getParameters();
+          }
+          if (parameters == null || parameters.length <= idx) continue;
+          PsiType parameterType = variant.getSubstitutor().substitute(parameters[idx].getType());
+          constraints.add(SubtypeConstraint.create(parameterType));
         }
       }
 
-      if (constraints.isEmpty()) makeDefault();
-      else {
+      if (!constraints.isEmpty()) {
         myResult = constraints.toArray(new TypeConstraint[constraints.size()]);
       }
     }
 
-    private int getIndex(GrArgumentList list) {
-      GrExpression[] arguments = list.getExpressionArguments();
-      for (int i = 0; i < arguments.length; i++) {
-        if (myExpression.equals(arguments[i])) return i;
-      }
-      return -1;
-    }
-
     public void visitAssignmentExpression(GrAssignmentExpression expression) {
       GrExpression rValue = expression.getRValue();
       if (myExpression.equals(rValue)) {
         PsiType lType = expression.getLValue().getType();
-        if (lType == null) makeDefault();
-        else {
+        if (lType != null) {
           myResult = new TypeConstraint[]{SubtypeConstraint.create(lType)};
         }
-      } else if (myExpression.equals(expression.getLValue())) {
-        if (rValue == null) makeDefault();
-        else {
+      }
+      else if (myExpression.equals(expression.getLValue())) {
+        if (rValue != null) {
           PsiType rType = rValue.getType();
-          if (rType == null) makeDefault();
-          else {
+          if (rType != null) {
             myResult = new TypeConstraint[]{SupertypeConstraint.create(rType)};
           }
         }
       }
     }
 
-    private void makeDefault() {
-      myResult = new TypeConstraint[]{
-          SubtypeConstraint.create("java.lang.Object", myExpression)
-      };
+    @Override
+    public void visitThrowStatement(GrThrowStatement throwStatement) {
+      final PsiClassType trowable = PsiType.getJavaLangTrowable(myExpression.getManager(), throwStatement.getResolveScope());
+      myResult = new TypeConstraint[]{SubtypeConstraint.create(trowable)};
     }
 
     public TypeConstraint[] getResult() {
index ae8a10706b319aed0015b54e91e00f71b0a31474..80821405f5215a1e0251c2d9b4f7435f14929467 100644 (file)
  */
 package org.jetbrains.plugins.groovy.lang.psi.expectedTypes;
 
+import com.intellij.psi.PsiClassType;
 import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiManager;
 import com.intellij.psi.PsiType;
-import com.intellij.psi.PsiClassType;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
+
 import static org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil.createType;
 
 /**
@@ -31,8 +35,8 @@ public  class SubtypeConstraint extends TypeConstraint {
     myDefaultType = defaultType;
   }
 
-  public boolean satisfied(PsiType type){
-    return myType.isAssignableFrom(type);
+  public boolean satisfied(PsiType type, PsiManager manager, GlobalSearchScope scope){
+    return TypesUtil.isAssignableByMethodCallConversion(getType(), type, manager, scope);
   }
 
   public PsiType getDefaultType() {
index dd43b02732a97c01b82d85e35d39633ce4359c0c..f982d7a069a2bf00f2f4311c462b8d1b8422359d 100644 (file)
  */
 package org.jetbrains.plugins.groovy.lang.psi.expectedTypes;
 
-import com.intellij.psi.PsiType;
-import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiClassType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.PsiType;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
+
 import static org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil.createType;
 
 /**
@@ -31,8 +35,8 @@ public  class SupertypeConstraint extends TypeConstraint {
     myDefaultType = defaultType;
   }
 
-  public boolean satisfied(PsiType type){
-    return type.isAssignableFrom(myType);
+  public boolean satisfied(PsiType type, PsiManager  manager, GlobalSearchScope scope){
+    return TypesUtil.isAssignableByMethodCallConversion(type, getType(), manager, scope);
   }
 
   public PsiType getDefaultType() {
index dda1bc58e69ce22d3f83de8e14fe340bc3614092..289041380684cabdd93d24e9cdb3b0193b07c775 100644 (file)
@@ -15,7 +15,9 @@
  */
 package org.jetbrains.plugins.groovy.lang.psi.expectedTypes;
 
+import com.intellij.psi.PsiManager;
 import com.intellij.psi.PsiType;
+import com.intellij.psi.search.GlobalSearchScope;
 
 /**
  * @author ven
@@ -23,7 +25,7 @@ import com.intellij.psi.PsiType;
 public abstract class TypeConstraint {
   protected final PsiType myType;
 
-  public abstract boolean satisfied(PsiType type);
+  public abstract boolean satisfied(PsiType type, PsiManager manager, GlobalSearchScope scope);
 
   public abstract PsiType getDefaultType();
 
index f451ccff15ee6aa80041631336aa37a2774d0835..2f45163941d36c0f0bed6560cdd536ef1aace95d 100644 (file)
  */
 package org.jetbrains.plugins.groovy.lang.psi.expectedTypes;
 
-import com.intellij.psi.PsiType;
-import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiClassType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.PsiType;
+import com.intellij.psi.search.GlobalSearchScope;
+
 import static org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil.createType;
 
 /**
@@ -28,7 +31,7 @@ public  class TypeEquals extends TypeConstraint {
     super(type);
   }
 
-  public boolean satisfied(PsiType type){
+  public boolean satisfied(PsiType type, PsiManager manager, GlobalSearchScope scope){
     return type.equals(myType);
   }
 
index e3049b8a6498c17c3e9c61f47c422867e163d6e6..24ab1063a72ce4e0ffd15e3e04ad809b4d2d3ae4 100644 (file)
@@ -208,8 +208,6 @@ public class TypesUtil {
       }
     }
 
-    if (lType.equalsToText(JAVA_LANG_STRING)) return true;
-
     rType = boxPrimitiveType(rType, manager, scope);
     lType = boxPrimitiveType(lType, manager, scope);
 
index c36ee4213ac413dbcddaabd67292a7a924630177..641f162090cac376fe036dfec07abaf7da893df2 100644 (file)
@@ -82,7 +82,7 @@ public class GroovyCompletionTest extends LightCodeInsightFixtureTestCase {
     myFixture.testCompletion(getTestName(false) + ".groovy", getTestName(false) + "_after.groovy");
   }
 
-public void testEachMethodForMapWithKeyValue() throws Throwable {
+  public void testEachMethodForMapWithKeyValue() throws Throwable {
     doBasicTest();
   }
 
@@ -267,7 +267,7 @@ public void testEachMethodForMapWithKeyValue() throws Throwable {
   }
 
   public void testPropertyWithSecondUpperLetter() throws Exception {
-    myFixture.testCompletionVariants(getTestName(false)+".groovy", "geteMail", "getePost");
+    myFixture.testCompletionVariants(getTestName(false) + ".groovy", "geteMail", "getePost");
   }
 
   public void testSmartCompletionInAssignmentExpression() throws Throwable {
@@ -286,4 +286,7 @@ public void testEachMethodForMapWithKeyValue() throws Throwable {
     doSmartCompletion("d1", "d2");
   }
 
+  public void testReturnStatement() throws Exception {
+    doSmartCompletion("b", "b1", "b2", "foo");
+  }
 }
diff --git a/plugins/groovy/testdata/groovy/completion/ReturnStatement.groovy b/plugins/groovy/testdata/groovy/completion/ReturnStatement.groovy
new file mode 100644 (file)
index 0000000..fae09e4
--- /dev/null
@@ -0,0 +1,6 @@
+boolean foo(String s, Date d) {
+  boolean b=true;
+  Boolean b1= false;
+  def b2=false;
+  return <caret>
+}
\ No newline at end of file