method refs: ambiguity with method refs inside

This commit is contained in:
anna
2012-10-01 20:49:07 +02:00
parent cb42e24da7
commit bd1f035718
4 changed files with 37 additions and 8 deletions

View File

@@ -32,6 +32,7 @@ import java.util.*;
*/
public class LambdaUtil {
private static final Logger LOG = Logger.getInstance("#" + LambdaUtil.class.getName());
public static ThreadLocal<Map<PsiMethodReferenceExpression, PsiType>> ourRefs = new ThreadLocal<Map<PsiMethodReferenceExpression, PsiType>>();
public static ThreadLocal<Set<PsiParameterList>> ourParams = new ThreadLocal<Set<PsiParameterList>>();
@Nullable
@@ -561,9 +562,23 @@ public class LambdaUtil {
return true;
}
public static boolean isAcceptable(@Nullable PsiMethodReferenceExpression methodReferenceExpression, PsiType left) {
public static boolean isAcceptable(@Nullable final PsiMethodReferenceExpression methodReferenceExpression, PsiType left) {
if (methodReferenceExpression == null) return false;
final JavaResolveResult result = methodReferenceExpression.advancedResolve(false);
Map<PsiMethodReferenceExpression, PsiType> map = ourRefs.get();
if (map == null) {
map = new HashMap<PsiMethodReferenceExpression, PsiType>();
ourRefs.set(map);
}
final JavaResolveResult result;
try {
if (map.put(methodReferenceExpression, left) != null) return false;
result = methodReferenceExpression.advancedResolve(false);
}
finally {
map.remove(methodReferenceExpression);
}
final PsiElement resolve = result.getElement();
if (resolve instanceof PsiMethod) {
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(left);

View File

@@ -43,6 +43,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase implements PsiMethodReferenceExpression {
private static Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiMethodReferenceExpressionImpl");
@@ -107,7 +108,11 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
LOG.error("invalid!");
return JavaResolveResult.EMPTY_ARRAY;
}
ResolveResult[] results = ResolveCache.getInstance(getProject()).resolveWithCaching(this, new MethodReferenceResolver(), true,
final MethodReferenceResolver resolver = new MethodReferenceResolver();
if (getFunctionalInterfaceType() == null) {
return (JavaResolveResult[])resolver.resolve(this, incompleteCode);
}
ResolveResult[] results = ResolveCache.getInstance(getProject()).resolveWithCaching(this, resolver, true,
incompleteCode);
return results.length == 0 ? JavaResolveResult.EMPTY_ARRAY : (JavaResolveResult[])results;
}
@@ -224,7 +229,16 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
final PsiElement element = getReferenceNameElement();
final boolean isConstructor = element instanceof PsiKeyword && PsiKeyword.NEW.equals(element.getText());
if (element instanceof PsiIdentifier || isConstructor) {
final PsiType functionalInterfaceType = getFunctionalInterfaceType();
PsiType functionalInterfaceType = getFunctionalInterfaceType();
if (functionalInterfaceType == null) {
final Map<PsiMethodReferenceExpression,PsiType> map = LambdaUtil.ourRefs.get();
if (map != null) {
functionalInterfaceType = map.get(PsiMethodReferenceExpressionImpl.this);
}
else {
functionalInterfaceType = null;
}
}
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
final MethodSignature signature = interfaceMethod != null ? interfaceMethod.getSignature(resolveResult.getSubstitutor()) : null;

View File

@@ -29,7 +29,7 @@ class MyTest {
{
Bar1 b1 = MyTest :: foo;
bar<error descr="Cannot resolve method 'bar(<method reference>)'">(MyTest :: foo)</error>;
bar<error descr="Ambiguous method call: both 'MyTest.bar(Bar1)' and 'MyTest.bar(Bar2)' match">(MyTest :: foo)</error>;
}
}

View File

@@ -55,12 +55,12 @@ class StaticInner {
class StaticInner1 {
static class Inner {
Inner(StaticInner outer) {}
Inner(StaticInner1 outer) {}
Inner() {}
}
interface I1 {
Inner _(StaticInner rec);
Inner _(StaticInner1 rec);
}
interface I2 {
@@ -71,6 +71,6 @@ class StaticInner1 {
static void call3(I2 s) {}
static {
call3<error descr="Cannot resolve method 'call3(<method reference>)'">(StaticInner.Inner :: new)</error>;
call3<error descr="Ambiguous method call: both 'StaticInner1.call3(I1)' and 'StaticInner1.call3(I2)' match">(StaticInner1.Inner :: new)</error>;
}
}