functional type: find common super type of intersection type's conjuncts (IDEA-144145)

This commit is contained in:
Anna Kozlova
2015-08-20 16:01:58 +02:00
parent 30ba5284f1
commit 08c0a88251
3 changed files with 39 additions and 3 deletions
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.daemon.impl.analysis;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.util.MethodSignature;
import com.intellij.psi.util.PsiTypesUtil;
@@ -25,12 +26,16 @@ import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* User: anna
*/
public class LambdaHighlightingUtil {
private static final Logger LOG = Logger.getInstance("#" + LambdaHighlightingUtil.class.getName());
@Nullable
public static String checkInterfaceFunctional(@NotNull PsiClass psiClass) {
return checkInterfaceFunctional(psiClass, "Target type of a lambda conversion must be an interface");
@@ -90,14 +95,16 @@ public class LambdaHighlightingUtil {
@Nullable
public static String checkInterfaceFunctional(PsiType functionalInterfaceType) {
if (functionalInterfaceType instanceof PsiIntersectionType) {
int count = 0;
final Set<MethodSignature> signatures = new HashSet<MethodSignature>();
for (PsiType type : ((PsiIntersectionType)functionalInterfaceType).getConjuncts()) {
if (checkInterfaceFunctional(type) == null) {
count++;
final MethodSignature signature = LambdaUtil.getFunction(PsiUtil.resolveClassInType(type));
LOG.assertTrue(signature != null, type.getCanonicalText());
signatures.add(signature);
}
}
if (count > 1) {
if (signatures.size() > 1) {
return "Multiple non-overriding abstract methods found in " + functionalInterfaceType.getPresentableText();
}
return null;
@@ -0,0 +1,12 @@
interface Z {
void m();
}
interface X extends Z {}
interface Y extends Z {}
class Test {
{
((X & <caret>Y) () -> {}).m();
}
}
@@ -18,7 +18,11 @@ package com.intellij.codeInsight.daemon.lambda;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.codeInsight.daemon.impl.analysis.LambdaHighlightingUtil;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiTypeCastExpression;
import com.intellij.psi.PsiTypeElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -86,4 +90,17 @@ public class FunctionalInterfaceTest extends LightDaemonAnalyzerTestCase {
public void testAbstractClass() throws Exception {
doTestFunctionalInterface("Target type of a lambda conversion must be an interface");
}
public void testIntersectionTypeWithSameBaseInterfaceInConjuncts() throws Exception {
String filePath = BASE_PATH + "/" + getTestName(false) + ".java";
configureByFile(filePath);
final PsiTypeCastExpression castExpression =
PsiTreeUtil.getParentOfType(getFile().findElementAt(getEditor().getCaretModel().getOffset()), PsiTypeCastExpression.class);
assertNotNull(castExpression);
final PsiTypeElement castTypeElement = castExpression.getCastType();
assertNotNull(castTypeElement);
final PsiType type = castTypeElement.getType();
final String errorMessage = LambdaHighlightingUtil.checkInterfaceFunctional(type);
assertEquals(null, errorMessage);
}
}