IDEA-62353 statically imported method is more relevant than all other variants

This commit is contained in:
Maxim.Medvedev
2012-03-30 12:12:54 +04:00
parent 12caa7219b
commit 1eb56239b7
5 changed files with 110 additions and 12 deletions
@@ -18,15 +18,19 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions;
import com.intellij.psi.*;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
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.api.statements.expressions.GrThisReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.processors.CompletionProcessor;
import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor;
import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mSPREAD_DOT;
@@ -41,6 +45,13 @@ public class GrReferenceResolveUtil {
public static boolean resolveImpl(ResolverProcessor processor, GrReferenceExpression place) {
GrExpression qualifier = place.getQualifier();
if (qualifier == null) {
if (processor instanceof MethodResolverProcessor || processor instanceof CompletionProcessor) {
processStaticImports(place.getContainingFile(), processor, ResolveState.initial(), place);
if (processor instanceof MethodResolverProcessor && ((MethodResolverProcessor)processor).hasApplicableCandidates()) {
return false;
}
}
if (!ResolveUtil.treeWalkUp(place, processor, true)) return false;
if (!processor.hasCandidates()) {
qualifier = PsiImplUtil.getRuntimeQualifier(place);
@@ -65,6 +76,18 @@ public class GrReferenceResolveUtil {
return true;
}
private static boolean processStaticImports(PsiFile file, ResolverProcessor processor, ResolveState state, PsiElement place) {
if (file instanceof GroovyFile) {
GrImportStatement[] imports = ((GroovyFile)file).getImportStatements();
for (GrImportStatement anImport : imports) {
if (anImport.isStatic()) {
if (!anImport.processDeclarations(processor, state, null, place)) return false;
}
}
}
return true;
}
public static boolean processIfJavaLangClass(ResolverProcessor processor,
PsiType type,
GroovyPsiElement resolveContext,
@@ -55,7 +55,7 @@ public class GrImportStatementImpl extends GroovyPsiElementImpl implements GrImp
public boolean processDeclarations(@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
PsiElement lastParent,
@Nullable PsiElement lastParent,
@NotNull PsiElement place) {
if (PsiTreeUtil.isAncestor(this, place, false)) {
return true;
@@ -60,6 +60,7 @@ public class MethodResolverProcessor extends ResolverProcessor {
public MethodResolverProcessor(String name, GroovyPsiElement place, boolean isConstructor, PsiType thisType, @Nullable PsiType[] argumentTypes, PsiType[] typeArguments) {
this(name, place, isConstructor, thisType, argumentTypes, typeArguments, false, false);
}
public MethodResolverProcessor(String name,
GroovyPsiElement place,
boolean isConstructor,
@@ -113,10 +114,6 @@ public class MethodResolverProcessor extends ResolverProcessor {
return true;
}
public PsiType getThisType() {
return myThisType;
}
@NotNull
public GroovyResolveResult[] getCandidates() {
if (!myAllVariants && super.hasCandidates()) {
@@ -215,10 +212,11 @@ public class MethodResolverProcessor extends ResolverProcessor {
return 0;
}
private static boolean isMoreConcreteThan(PsiMethod method, @NotNull final PsiSubstitutor substitutor,
@NotNull PsiMethod another,
@NotNull PsiSubstitutor anotherSubstitutor,
@NotNull GroovyPsiElement context) {
private static boolean isMoreConcreteThan(@NotNull PsiMethod method,
@NotNull final PsiSubstitutor substitutor,
@NotNull PsiMethod another,
@NotNull PsiSubstitutor anotherSubstitutor,
@NotNull GroovyPsiElement context) {
if (another instanceof GrGdkMethodImpl && another.getName().equals(method.getName())) {
final PsiParameter[] plusParameters = method.getParameterList().getParameters();
final PsiParameter[] defParameters = another.getParameterList().getParameters();
@@ -76,7 +76,7 @@ public abstract class GroovyResolveTestCase extends LightGroovyTestCase {
}
protected PsiReference configureByText(String text) {
configureByText('a.groovy', text);
configureByText('_a.groovy', text);
}
protected PsiReference configureByText(String fileName, String text) {
@@ -17,6 +17,7 @@
package org.jetbrains.plugins.groovy.lang.resolve;
import com.intellij.psi.util.PropertyUtil
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression
@@ -29,7 +30,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrRe
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl
import org.jetbrains.plugins.groovy.util.TestUtils
import com.intellij.psi.*
import com.intellij.psi.util.PropertyUtil
/**
* @author ven
@@ -37,7 +37,7 @@ import com.intellij.psi.util.PropertyUtil
public class ResolveMethodTest extends GroovyResolveTestCase {
@Override
protected String getBasePath() {
return TestUtils.getTestDataPath() + "resolve/method/";
return TestUtils.testDataPath + "resolve/method/";
}
@@ -863,4 +863,81 @@ def scriptMethod(String s){}
assertNull(ref.resolve())
}
public void testStaticallyImportedMethodsVsDGMMethods() {
myFixture.addClass('''\
package p;
public class Matcher{}
''' )
myFixture.addClass('''\
package p;
class Other {
public static Matcher is(Matcher m){}
public static Matcher create(){}
}''')
def ref = configureByText('''\
import static p.Other.is
import static p.Other.create
i<caret>s(create())
''')
def resolved = ref.resolve()
assertInstanceOf resolved, PsiMethod
assertEquals 'Other', resolved.containingClass.name
}
public void testStaticallyImportedMethodsVsCurrentClassMethod() {
myFixture.addClass('''\
package p;
class Other {
public static Object is(Object m){}
}''')
def ref = configureByText('''\
import static p.Other.is
class A {
public boolean is(String o){true}
public foo() {
print i<caret>s('abc')
}
}
''')
def resolved = ref.resolve()
assertInstanceOf resolved, PsiMethod
assertEquals 'Other', resolved.containingClass.name
}
public void testInapplicableStaticallyImportedMethodsVsCurrentClassMethod() {
myFixture.addClass('''\
package p;
class Other {
public static Object is(String m){}
}''')
def ref = configureByText('''\
import static p.Other.is
class A {
public boolean is(Object o){true}
public foo() {
print i<caret>s(new Object())
}
}
''')
def resolved = ref.resolve()
assertInstanceOf resolved, PsiMethod
assertEquals 'A', resolved.containingClass.name
}
}