method refs: testdata; varargs

This commit is contained in:
anna
2012-09-28 20:32:59 +02:00
parent 96482dd326
commit b7ca327ee3
4 changed files with 169 additions and 6 deletions

View File

@@ -575,7 +575,7 @@ public class LambdaUtil {
final MethodSignature signature1 = method.getSignature(resolveResult.getSubstitutor());
final MethodSignature signature2 = ((PsiMethod)resolve).getSignature(substRef.get());
if (areAcceptable(signature1, signature2, classRef.get(), substRef.get())) return true;
if (areAcceptable(signature1, signature2, classRef.get(), substRef.get(), ((PsiMethod)resolve).isVarArgs())) return true;
}
}
return false;
@@ -584,7 +584,8 @@ public class LambdaUtil {
public static boolean areAcceptable(MethodSignature signature1,
MethodSignature signature2,
PsiClass psiClass,
PsiSubstitutor psiSubstitutor) {
PsiSubstitutor psiSubstitutor,
boolean isVarargs) {
int offset = 0;
final PsiType[] signatureParameterTypes1 = signature1.getParameterTypes();
final PsiType[] signatureParameterTypes2 = signature2.getParameterTypes();
@@ -596,7 +597,7 @@ public class LambdaUtil {
(receiverType instanceof PsiClassType && ((PsiClassType)receiverType).isRaw() && receiverType.equals(TypeConversionUtil.erasure(classType)))) {
offset++;
}
else {
else if (!isVarargs){
return false;
}
}
@@ -605,9 +606,10 @@ public class LambdaUtil {
}
}
for (int i = 0; i < signatureParameterTypes2.length; i++) {
final int min = Math.min(signatureParameterTypes2.length, signatureParameterTypes1.length);
for (int i = 0; i < min; i++) {
final PsiType type1 = signatureParameterTypes1[offset + i];
final PsiType type2 = signatureParameterTypes2[i];
final PsiType type2 = isVarargs && i == min - 1 ? ((PsiArrayType)signatureParameterTypes2[i]).getComponentType() : signatureParameterTypes2[i];
if (!GenericsUtil.eliminateWildcards(psiSubstitutor.substitute(type1)).equals(GenericsUtil.eliminateWildcards(type2))) {
return false;
}

View File

@@ -282,7 +282,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
PsiSubstitutor subst = PsiSubstitutor.EMPTY;
subst = subst.putAll(mySubstitutor);
if (!LambdaUtil.areAcceptable(mySignature,
psiMethod.getSignature(subst.putAll(conflict.getSubstitutor())), myContainingClass, mySubstitutor)) {
psiMethod.getSignature(subst.putAll(conflict.getSubstitutor())), myContainingClass, mySubstitutor, psiMethod.isVarArgs())) {
iterator.remove();
}
}

View File

@@ -1,3 +1,4 @@
import java.util.*;
class MyTest {
static void m(int i) {//here
@@ -56,3 +57,141 @@ class MyTest2 {
call<error descr="Cannot resolve method 'call(int, <method reference>)'">(1, MyTest2::m)</error>; //ambiguous
}
}
class MyTest3 {
interface I {
void m();
}
MyTest3() {}
static void m() { }
public static void main(String[] args) {
I s = new MyTest3()::m;
}
}
class MyTest4 {
interface I {
MyTest4 m(List<Integer> l1, List<Integer> l2);
}
MyTest4 meth(List<Integer>... lli) { return null; }
MyTest4(List<Integer>... lli) { }
I s1 = this::meth;
I s2 = MyTest4::new;
}
class MyTest5 {
interface I_void<X> {
void m();
}
interface I_Void<X> {
void m();
}
static void m_void() {}
static Void _Void() {return null; }
public static void main(String[] args) {
I_void s1 = MyTest5::m_void;
s1.m();
I_Void s2 = MyTest5::m_void;
s2.m();
I_void s3 = MyTest5::_Void;
s3.m();
I_Void s4 = MyTest5::_Void;
s4.m();
}
}
class MyTest6 {
interface I {
MyTest6 invoke();
}
MyTest6() {
}
static MyTest6 m() {
return null;
}
public static void main(String[] args) {
I I1 = ((I)() -> {return null; })::invoke;
I1.invoke();
I I2 = ((I)MyTest6::new)::invoke;
I1.invoke();
I I3 = ((I)MyTest6::m)::invoke;
I1.invoke();
}
}
class MyTest7{
interface I<R> {
R invoke();
}
@interface A { }
static abstract class AC { }
enum E { }
void test() {
<error descr="Incompatible types. Found: '<method reference>', required: 'MyTest7.I'">I s1 = A::new;</error>
<error descr="Incompatible types. Found: '<method reference>', required: 'MyTest7.I'">I s2 = I::new;</error>
<error descr="Incompatible types. Found: '<method reference>', required: 'MyTest7.I'">I s3 = AC::new;</error>
<error descr="Incompatible types. Found: '<method reference>', required: 'MyTest7.I'">I s4 = E::new;</error>
}
}
class MyTest8{
static class Sup {}
static class Sub extends Sup {
interface I { Sup m(Sup x, String str); }
class Inner extends Sup {
Inner(String val) { }
}
void test() {
<error descr="Incompatible types. Found: '<method reference>', required: 'MyTest8.Sub.I'">I var = Sub.Inner::new;</error>;
}
}
}
class MyTest9 {
static class SuperFoo<X> { }
static class Foo<X extends Number> extends SuperFoo<X> { }
interface I1 {
void m();
}
interface I2 {
void m();
}
static <X extends Number> Foo<X> m() { return null; }
static void g1(I1 s) { }
static void g2(I1 s) { }
static void g2(I2 s) { }
void test() {
g1(MyTest9::m);
g2<error descr="Ambiguous method call: both 'MyTest9.g2(I1)' and 'MyTest9.g2(I2)' match">(MyTest9::m)</error>;
}
}

View File

@@ -0,0 +1,22 @@
class MethodReference27 {
interface SAM {
void m(int i1, int i2);
}
static void m1(int i1, int i2) { }
static void m1(Integer i1, int i2) { }
static void m1(int i1, Integer i2) { }
static void m1(Integer i1, Integer i2) {}
static void m1(Integer... is) { }
static void m2(int... is) { }
static void m2(double... ds) {}
public static void main(String[] args) {
SAM s1 = MethodReference27::m1;
s1.m(42,42);
SAM s2 = MethodReference27 :: m2;
s2.m(42,42);
}
}