method refs: collect substitution from type parameter's extends list (IDEA-104314)

This commit is contained in:
anna
2013-04-01 20:36:27 +02:00
parent 119870c301
commit 497644d544
3 changed files with 111 additions and 2 deletions
@@ -359,9 +359,9 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
final PsiType[] types = method.getSignature(PsiUtil.isRawSubstitutor(method, substitutor) ? PsiSubstitutor.EMPTY : substitutor).getParameterTypes();
final PsiType[] rightTypes = signature.getParameterTypes();
if (types.length < rightTypes.length) {
return PsiUtil.resolveGenericsClassInType(rightTypes[0]).getSubstitutor();
return getSubstitutor(rightTypes[0]);
} else if (types.length > rightTypes.length) {
return PsiUtil.resolveGenericsClassInType(types[0]).getSubstitutor();
return getSubstitutor(types[0]);
}
for (int i = 0; i < rightTypes.length; i++) {
@@ -381,6 +381,20 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
languageLevel, PsiMethodReferenceExpressionImpl.this.getProject());
}
private PsiSubstitutor getSubstitutor(PsiType type) {
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(type);
PsiSubstitutor psiSubstitutor = resolveResult.getSubstitutor();
if (type instanceof PsiClassType) {
final PsiClass psiClass = resolveResult.getElement();
if (psiClass instanceof PsiTypeParameter) {
for (PsiClass aClass : psiClass.getSupers()) {
psiSubstitutor = psiSubstitutor.putAll(TypeConversionUtil.getSuperClassSubstitutor(aClass, (PsiClassType)type));
}
}
}
return psiSubstitutor;
}
private class MethodReferenceConflictResolver implements PsiConflictResolver {
private final PsiClass myContainingClass;
private final PsiSubstitutor mySubstitutor;
@@ -0,0 +1,91 @@
interface AdditiveGroupValue<A> {
A negative();
}
interface Vector<S extends AdditiveGroupValue<S>> {
default void foo() {
Foo<S> negative = AdditiveGroupValue::negative;
}
}
interface Foo<T> {
T bar(T t);
}
class Test1 {
interface AdditiveGroupValue<V extends AdditiveGroupValue<V>> {
V plus(V other);
V negative();
default V minus(V other) {
return self().plus(other.negative());
}
V self();
Class<?> valueClass();
}
interface Vector<S extends AdditiveGroupValue<S>, V extends Vector<S, V>> extends AdditiveGroupValue<V> {
S get(int i);
int size();
@Override
default V plus(V other) {
return Vectors.binaryComponentOp(self(), other, AdditiveGroupValue::plus);
}
@Override
default V minus(V other) {
return Vectors.binaryComponentOp(self(), other, AdditiveGroupValue::minus);
}
@Override
default V negative() {
return Vectors.unaryComponentOp(self(), AdditiveGroupValue::negative);
}
V valueOf(S[] components);
}
interface UnaryOperator<T> {
T apply(T r);
}
interface BinaryOperator<T> {
T apply(T r, T t);
}
static class Vectors {
public static <S extends AdditiveGroupValue<S>, V extends Vector<S, V>> V unaryComponentOp(V v1, UnaryOperator<S> op) {
int size = v1.size();
S[] components = newComponentArray(v1.valueClass(), size);
for (int i = 0; i < size; i++) {
components[i] = op.apply(v1.get(i));
}
return v1.valueOf(components);
}
public static <S extends AdditiveGroupValue<S>, V extends Vector<S, V>> V binaryComponentOp(V v1, V v2, BinaryOperator<S> op) {
int size = v1.size();
S[] components = newComponentArray(v1.valueClass(), size);
for (int i = 0; i < size; i++) {
components[i] = op.apply(v1.get(i), v2.get(i));
}
return v1.valueOf(components);
}
protected static <S extends AdditiveGroupValue<S>> S[] newComponentArray(Class<?> componentClass, int size) {
return null;
}
}
}
@@ -79,6 +79,10 @@ public class MethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testAbstractMethod() { doTest(); }
public void testMethodRefAcceptance() { doTest(); }
public void testTypeParameterWithExtendsList() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}