diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java index 8dc811e6258d..503328ab46c5 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java @@ -36,7 +36,7 @@ public class LambdaHighlightingUtil { @Nullable public static String checkInterfaceFunctional(@NotNull PsiClass psiClass, String interfaceNonFunctionalMessage) { if (psiClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference - final List signatures = LambdaUtil.findFunctionCandidates(psiClass); + final List signatures = LambdaUtil.findFunctionCandidates(psiClass); if (signatures == null) return interfaceNonFunctionalMessage; if (signatures.isEmpty()) return "No target method found"; if (signatures.size() == 1) { @@ -113,7 +113,7 @@ public class LambdaHighlightingUtil { final PsiClass aClass = resolveResult.getElement(); if (aClass != null) { if (aClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference - final List signatures = LambdaUtil.findFunctionCandidates(aClass); + final List signatures = LambdaUtil.findFunctionCandidates(aClass); if (signatures != null && signatures.size() == 1) { final MethodSignature functionalMethod = signatures.get(0); if (functionalMethod.getTypeParameters().length > 0) return "Target method is generic"; diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index 09b9cdd48e64..fcf5e8945e7a 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -112,7 +112,7 @@ public class LambdaUtil { public static boolean isFunctionalClass(PsiClass aClass) { if (aClass != null) { if (aClass instanceof PsiTypeParameter) return false; - final List signatures = findFunctionCandidates(aClass); + final List signatures = findFunctionCandidates(aClass); return signatures != null && signatures.size() == 1; } return false; @@ -142,7 +142,7 @@ public class LambdaUtil { @Nullable static MethodSignature getFunction(PsiClass psiClass) { if (psiClass == null) return null; - final List functions = findFunctionCandidates(psiClass); + final List functions = findFunctionCandidates(psiClass); if (functions != null && functions.size() == 1) { return functions.get(0); } @@ -176,13 +176,13 @@ public class LambdaUtil { } @Nullable - private static List hasSubsignature(List signatures) { - for (MethodSignature signature : signatures) { + private static List hasSubsignature(List signatures) { + for (HierarchicalMethodSignature signature : signatures) { boolean subsignature = true; - for (MethodSignature methodSignature : signatures) { + for (HierarchicalMethodSignature methodSignature : signatures) { if (!signature.equals(methodSignature)) { - if (!MethodSignatureUtil.isSubsignature(signature, methodSignature) && - methodSignature.getTypeParameters().length == 0) { + if (!MethodSignatureUtil.isSubsignature(signature, methodSignature) && + !skipMethod(signature, methodSignature)) { subsignature = false; break; } @@ -193,10 +193,20 @@ public class LambdaUtil { return signatures; } + private static boolean skipMethod(HierarchicalMethodSignature signature, + HierarchicalMethodSignature methodSignature) { + //not generic + if (methodSignature.getTypeParameters().length == 0) { + return false; + } + //foreign class + return signature.getMethod().getContainingClass() != methodSignature.getMethod().getContainingClass(); + } + @Nullable - public static List findFunctionCandidates(PsiClass psiClass) { + public static List findFunctionCandidates(PsiClass psiClass) { if (psiClass != null && psiClass.isInterface() && !psiClass.isAnnotationType()) { - final List methods = new ArrayList(); + final List methods = new ArrayList(); final Collection visibleSignatures = psiClass.getVisibleSignatures(); for (HierarchicalMethodSignature signature : visibleSignatures) { final PsiMethod psiMethod = signature.getMethod(); @@ -364,7 +374,7 @@ public class LambdaUtil { @Nullable private static PsiType extractFunctionalConjunct(PsiIntersectionType type) { PsiType conjunct = null; - for (PsiType conjunctType : ((PsiIntersectionType)type).getConjuncts()) { + for (PsiType conjunctType : type.getConjuncts()) { final PsiMethod interfaceMethod = getFunctionalInterfaceMethod(conjunctType); if (interfaceMethod != null) { if (conjunct != null && !conjunct.equals(conjunctType)) return null; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/GenericNotGenericInterfaceMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/GenericNotGenericInterfaceMethod.java index 9cb75abb0c80..71b286a5268e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/GenericNotGenericInterfaceMethod.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/GenericNotGenericInterfaceMethod.java @@ -14,3 +14,30 @@ class Test { C c = ()-> {}; } } + +class Test1 { + + interface F { + void m(); + } + + { + F f = this::g; + } + + void g() {} +} + +class Test2 { + + interface F { + void m(); + void a(); + } + + { + F f = () -> g(); + } + + void g() {} +} diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java index e4f77e0fbea9..b9f43f708b77 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java @@ -75,7 +75,7 @@ public class InterfaceMayBeAnnotatedFunctionalInspection extends BaseInspection if (LambdaHighlightingUtil.checkInterfaceFunctional(aClass) != null) { return; } - final List candidates = LambdaUtil.findFunctionCandidates(aClass); + final List candidates = LambdaUtil.findFunctionCandidates(aClass); if (candidates == null || candidates.size() != 1) { return; }