From 99e4c75ee7662b7cf59b4b68ac27d480803b36e6 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 7 Jan 2016 15:40:24 +0100 Subject: [PATCH] inherit unrelated abstract/default through hierarchy: don't merge methods with not override equivalent signatures (IDEA-146135) --- .../impl/analysis/GenericsHighlightUtil.java | 10 ++- ...ferentMethodsBecomeOverrideEquivalent.java | 85 +++++++++++++++++++ .../Interface8MethodsHighlightingTest.java | 4 + 3 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/SubsignatureCheckWhen2DifferentMethodsBecomeOverrideEquivalent.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 7d0be495f790..67b77e18aae8 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -457,8 +457,8 @@ public class GenericsHighlightUtil { if (aClass.findMethodsBySignature(method, false).length > 0) continue; final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) continue; - final PsiSubstitutor containingClassSubstitutor = - TypeConversionUtil.getSuperClassSubstitutor(containingClass, aClass, PsiSubstitutor.EMPTY); + final PsiSubstitutor containingClassSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, aClass, PsiSubstitutor.EMPTY); + if (containingClassSubstitutor == null) continue; final PsiSubstitutor finalSubstitutor = PsiSuperMethodImplUtil.obtainFinalSubstitutor(containingClass, containingClassSubstitutor, hms.getSubstitutor(), false); final MethodSignatureBackedByPsiMethod signature = MethodSignatureBackedByPsiMethod.create(method, finalSubstitutor, false); @@ -499,7 +499,11 @@ public class GenericsHighlightUtil { final PsiClass unrelatedMethodContainingClass = unrelatedMethod.getContainingClass(); if (unrelatedMethodContainingClass == null) continue; if (!aClass.hasModifierProperty(PsiModifier.ABSTRACT) && astracts != null && unrelatedMethodContainingClass.isInterface()) { - if (defaultMethodContainingClass.isInheritor(unrelatedMethodContainingClass, true)) continue; + if (defaultMethodContainingClass.isInheritor(unrelatedMethodContainingClass, true) && + MethodSignatureUtil.isSubsignature(unrelatedMethod.getSignature(PsiSubstitutor.EMPTY), + defaultMethod.getSignature(PsiSubstitutor.EMPTY))) { + continue; + } final String key = aClass instanceof PsiEnumConstantInitializer ? "enum.constant.should.implement.method" : "class.must.be.abstract"; final String message = JavaErrorMessages.message(key, HighlightUtil.formatClass(aClass, false), JavaHighlightUtil.formatMethod(astracts.get(0)), HighlightUtil.formatClass(unrelatedMethodContainingClass, false)); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/SubsignatureCheckWhen2DifferentMethodsBecomeOverrideEquivalent.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/SubsignatureCheckWhen2DifferentMethodsBecomeOverrideEquivalent.java new file mode 100644 index 000000000000..5ee6cfbe3616 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/SubsignatureCheckWhen2DifferentMethodsBecomeOverrideEquivalent.java @@ -0,0 +1,85 @@ + +class Test1 { + interface A { + void foo(String x); + } + + interface C extends A { + + default void foo(T x) { } + } + + class D implements C { } + interface E extends C { } +} + +class Test2 { + interface A { + default void foo(String x) {} + } + + interface C extends A { + + void foo(T x); + } + + class D implements C {} + interface E extends C {} +} + +class Test3 { + interface A { + default void foo(String x) {} + } + + interface C extends A { + + default void foo(T x) {} + } + + class D implements C { } + interface E extends C { } +} + +class Test4 { + interface A { + void foo(String x); + } + + interface C extends A { + + void foo(T x); + } + + abstract class D implements C, A { } + interface E extends C, A {} +} + +class Test5 { + interface A { + void foo(String x); + } + + abstract class B implements A { } + + interface C extends A { + default void foo(T x) { } + } + + class D extends B implements C { } +} + + +class Test6 { + interface A { + default void foo(String s) { } + } + + interface B extends A {} + + interface C extends A { + default void foo(T t) {} + } + abstract static class D implements C, B { } + static class E extends D {} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java index 53063b0d70ca..40ba71840115 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java @@ -93,6 +93,10 @@ public class Interface8MethodsHighlightingTest extends LightCodeInsightFixtureTe doTest(); } + public void testSubsignatureCheckWhen2DifferentMethodsBecomeOverrideEquivalent() throws Exception { + doTest(); + } + private void doTest() { doTest(false, false); }