diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/java/UnimplementedKotlinInterfaceMemberAnnotator.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/java/UnimplementedKotlinInterfaceMemberAnnotator.kt index 24a15f3c7a7..7c591fe22c4 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/java/UnimplementedKotlinInterfaceMemberAnnotator.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/java/UnimplementedKotlinInterfaceMemberAnnotator.kt @@ -29,6 +29,7 @@ import com.intellij.psi.* import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.resolve.annotations.JVM_DEFAULT_FQ_NAME import org.jetbrains.kotlin.utils.ifEmpty class UnimplementedKotlinInterfaceMemberAnnotator : Annotator { @@ -51,10 +52,14 @@ class UnimplementedKotlinInterfaceMemberAnnotator : Annotator { }.ifEmpty { return null } val kotlinSuperClass = generateSequence(psiClass) { it.superClass }.firstOrNull { it is KtLightClassForSourceDeclaration } - ?: return signaturesFromKotlinInterfaces.first().method as? KtLightMethod - val signaturesVisibleThroughKotlinSuperClass = kotlinSuperClass.visibleSignatures - return signaturesFromKotlinInterfaces.firstOrNull { it !in signaturesVisibleThroughKotlinSuperClass }?.method as? KtLightMethod + val signaturesVisibleThroughKotlinSuperClass = kotlinSuperClass?.visibleSignatures ?: emptyList() + return signaturesFromKotlinInterfaces.firstOrNull { + it !in signaturesVisibleThroughKotlinSuperClass && + it.method.annotations.none { annotation -> + annotation.qualifiedName == JVM_DEFAULT_FQ_NAME.asString() + } + }?.method as? KtLightMethod } private fun report(method: KtLightMethod, holder: AnnotationHolder, psiClass: PsiClass) { diff --git a/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendClassWithJvmDefaultImplementation.java b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendClassWithJvmDefaultImplementation.java new file mode 100644 index 00000000000..8b50a32f63f --- /dev/null +++ b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendClassWithJvmDefaultImplementation.java @@ -0,0 +1,11 @@ +package test; + +public class ExtendClassWithJvmDefaultImplementation { + public static class ExtendClass extends KotlinClass { + + } + + public static class ImplementInterface implements KotlinInterface { + + } +} diff --git a/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendClassWithJvmDefaultImplementation.kt b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendClassWithJvmDefaultImplementation.kt new file mode 100644 index 00000000000..4a09374d6a6 --- /dev/null +++ b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendClassWithJvmDefaultImplementation.kt @@ -0,0 +1,17 @@ +package test + +interface KotlinInterface { + @JvmDefault + fun bar() { + + } + +// @JvmDefault +// val foo: String +// get() = "123" +} + + +abstract class KotlinClass : KotlinInterface { + +} \ No newline at end of file diff --git a/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendClassWithJvmDefaultImplementation.txt b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendClassWithJvmDefaultImplementation.txt new file mode 100644 index 00000000000..39b5a644279 --- /dev/null +++ b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendClassWithJvmDefaultImplementation.txt @@ -0,0 +1,2 @@ +// LANGUAGE_LEVEL 1.8 +// WITH_RUNTIME \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinBinariesCheckerTestGenerated.java b/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinBinariesCheckerTestGenerated.java index 6080dc8da55..348c63ec08f 100644 --- a/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinBinariesCheckerTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinBinariesCheckerTestGenerated.java @@ -74,6 +74,11 @@ public class JavaAgainstKotlinBinariesCheckerTestGenerated extends AbstractJavaA runTest("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendClassWithDefaultImplementation_1_8.kt"); } + @TestMetadata("ExtendClassWithJvmDefaultImplementation.kt") + public void testExtendClassWithJvmDefaultImplementation() throws Exception { + runTest("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendClassWithJvmDefaultImplementation.kt"); + } + @TestMetadata("ExtendingMutableInterfaces.kt") public void testExtendingMutableInterfaces() throws Exception { runTest("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendingMutableInterfaces.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinSourceCheckerTestGenerated.java b/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinSourceCheckerTestGenerated.java index 8931fc143b6..fb0479f4f11 100644 --- a/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinSourceCheckerTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/checkers/JavaAgainstKotlinSourceCheckerTestGenerated.java @@ -76,6 +76,11 @@ public class JavaAgainstKotlinSourceCheckerTestGenerated extends AbstractJavaAga runTest("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendClassWithDefaultImplementation_1_8.kt"); } + @TestMetadata("ExtendClassWithJvmDefaultImplementation.kt") + public void testExtendClassWithJvmDefaultImplementation() throws Exception { + runTest("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendClassWithJvmDefaultImplementation.kt"); + } + @TestMetadata("ExtendingMutableInterfaces.kt") public void testExtendingMutableInterfaces() throws Exception { runTest("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendingMutableInterfaces.kt");