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;
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");
@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;
--- /dev/null
+interface Z {
+ void m();
+}
+
+interface X extends Z {}
+interface Y extends Z {}
+
+class Test {
+ {
+ ((X & <caret>Y) () -> {}).m();
+ }
+}
\ No newline at end of file
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;
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);
+ }
}