functional interfaces: allow intersection with 2 independent abstract methods with same signature (IDEA-171622)

This commit is contained in:
Anna.Kozlova
2017-04-21 19:31:38 +02:00
parent d680d55c99
commit 58fcabfd2b
4 changed files with 53 additions and 7 deletions

View File

@@ -514,13 +514,21 @@ public class LambdaUtil {
@Nullable
private static PsiType extractFunctionalConjunct(PsiIntersectionType type) {
PsiType conjunct = null;
for (PsiType conjunctType : type.getConjuncts()) {
final PsiMethod interfaceMethod = getFunctionalInterfaceMethod(conjunctType);
if (interfaceMethod != null) {
if (conjunct != null && !conjunct.equals(conjunctType)) return null;
conjunct = conjunctType;
MethodSignature commonSignature = null;
for (PsiType psiType : type.getConjuncts()) {
PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(psiType);
if (aClass instanceof PsiTypeParameter) continue;
MethodSignature signature = getFunction(aClass);
if (signature == null) continue;
if (commonSignature == null) {
commonSignature = signature;
}
else if (!MethodSignatureUtil.areSignaturesEqual(commonSignature, signature)) {
return null;
}
conjunct = psiType;
}
return conjunct;
}

View File

@@ -0,0 +1,13 @@
interface X {
void m(Integer i);
}
interface Y<T> {
void m(T t);
}
class Test {
{
((X & <caret>Y<Integer>) (x) -> {}).m(1);
}
}

View File

@@ -0,0 +1,13 @@
interface X {
void m();
}
interface Y {
void m();
}
class Test {
{
((X & <caret>Y) () -> {}).m();
}
}

View File

@@ -53,7 +53,15 @@ public class FunctionalInterfaceTest extends LightDaemonAnalyzerTestCase {
public void testMultipleMethodsInOne() throws Exception {
doTestFunctionalInterface(null);
}
}
public void testIntersectionOf2FunctionalTypesWithEqualSignatures() throws Exception {
doTestIntersection(null);
}
public void testIntersectionOf2FunctionalTypesWithEqualAfterSubstitutionSignatures() throws Exception {
doTestIntersection("Multiple non-overriding abstract methods found in X & Y<Integer>");
}
public void testClone() throws Exception {
doTestFunctionalInterface("Multiple non-overriding abstract methods found in interface Foo");
@@ -92,6 +100,10 @@ public class FunctionalInterfaceTest extends LightDaemonAnalyzerTestCase {
}
public void testIntersectionTypeWithSameBaseInterfaceInConjuncts() throws Exception {
doTestIntersection(null);
}
private void doTestIntersection(final String expectedMessage) {
String filePath = BASE_PATH + "/" + getTestName(false) + ".java";
configureByFile(filePath);
final PsiTypeCastExpression castExpression =
@@ -101,6 +113,6 @@ public class FunctionalInterfaceTest extends LightDaemonAnalyzerTestCase {
assertNotNull(castTypeElement);
final PsiType type = castTypeElement.getType();
final String errorMessage = LambdaHighlightingUtil.checkInterfaceFunctional(type);
assertEquals(null, errorMessage);
assertEquals(expectedMessage, errorMessage);
}
}