diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java index 35e24fa88bd2..52e9ab691092 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java @@ -4,6 +4,7 @@ import com.intellij.codeInsight.MemberImplementorExplorer; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.util.MethodSignature; @@ -63,9 +64,9 @@ public class OverrideImplementExploreUtil { } Map map = hisClass.isInterface() || method.hasModifierProperty(PsiModifier.ABSTRACT) ? abstracts : concretes; - PsiMethod other = map.get(signature); - if (other == null || preferLeftForImplement(method, other)) { - map.put(signature, method); + fillMap(signature, method, map); + if (isDefaultMethod(aClass, method)) { + fillMap(signature, method, concretes); } } @@ -92,6 +93,18 @@ public class OverrideImplementExploreUtil { return result; } + private static boolean isDefaultMethod(PsiClass aClass, PsiMethod method) { + return method.hasModifierProperty(PsiModifier.DEFAULT) && + PsiUtil.getLanguageLevel(aClass).isAtLeast(LanguageLevel.JDK_1_8); + } + + private static void fillMap(HierarchicalMethodSignature signature, PsiMethod method, Map map) { + final PsiMethod other = map.get(signature); + if (other == null || preferLeftForImplement(method, other)) { + map.put(signature, method); + } + } + public static void collectMethodsToImplement(PsiClass aClass, Map abstracts, Map finals, @@ -103,7 +116,8 @@ public class OverrideImplementExploreUtil { PsiMethod concrete = concretes.get(signature); if (concrete == null || PsiUtil.getAccessLevel(concrete.getModifierList()) < PsiUtil.getAccessLevel(abstractOne.getModifierList()) - || !abstractOne.getContainingClass().isInterface() && abstractOne.getContainingClass().isInheritor(concrete.getContainingClass(), true)) { + || !abstractOne.getContainingClass().isInterface() && abstractOne.getContainingClass().isInheritor(concrete.getContainingClass(), true) + || isDefaultMethod(aClass, abstractOne)) { if (finals.get(signature) == null) { PsiSubstitutor subst = correctSubstitutor(abstractOne, signature.getSubstitutor()); CandidateInfo info = new CandidateInfo(abstractOne, subst); diff --git a/java/java-tests/testData/codeInsight/overrideImplement/afterOverrideExtensionMethods.java b/java/java-tests/testData/codeInsight/overrideImplement/afterOverrideExtensionMethods.java new file mode 100644 index 000000000000..c9cc68b01537 --- /dev/null +++ b/java/java-tests/testData/codeInsight/overrideImplement/afterOverrideExtensionMethods.java @@ -0,0 +1,39 @@ +interface A { + default void m(T t) { } +} + +class MyClass implements A { + @Override + public void m(T t) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public MyClass() { + super(); //To change body of overridden methods use File | Settings | File Templates. + } + + @Override + public int hashCode() { + return super.hashCode(); //To change body of overridden methods use File | Settings | File Templates. + } + + @Override + public boolean equals(Object obj) { + return super.equals(obj); //To change body of overridden methods use File | Settings | File Templates. + } + + @Override + protected Object clone() throws CloneNotSupportedException { + return super.clone(); //To change body of overridden methods use File | Settings | File Templates. + } + + @Override + public String toString() { + return super.toString(); //To change body of overridden methods use File | Settings | File Templates. + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); //To change body of overridden methods use File | Settings | File Templates. + } +} diff --git a/java/java-tests/testData/codeInsight/overrideImplement/beforeOverrideExtensionMethods.java b/java/java-tests/testData/codeInsight/overrideImplement/beforeOverrideExtensionMethods.java new file mode 100644 index 000000000000..40920991631c --- /dev/null +++ b/java/java-tests/testData/codeInsight/overrideImplement/beforeOverrideExtensionMethods.java @@ -0,0 +1,7 @@ +interface A { + default void m(T t) { } +} + +class MyClass implements A { + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.java index 9349bcb2a4d5..a5be3591b236 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.java @@ -66,6 +66,7 @@ public class OverrideImplementTest extends LightCodeInsightTestCase { public void testResolveTypeParamConflict() { doTest(false); } public void testImplementExtensionMethods() { doTest8(false, true); } + public void testOverrideExtensionMethods() { doTest8(false, false); } public void testDoNotImplementExtensionMethods() { doTest8(false, true); } public void testLongFinalParameterList() {