diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt index a4319ae886b..db8275a0c2b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt @@ -32,7 +32,7 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier import org.jetbrains.kotlin.resolve.BindingContext.* -import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers +import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractDeclaration import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveOpenMembers import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns @@ -585,7 +585,7 @@ class DeclarationsChecker( if (modifierList != null) { if (modifierList.hasModifier(KtTokens.ABSTRACT_KEYWORD)) { //has abstract modifier - if (!classCanHaveAbstractMembers(classDescriptor)) { + if (!classCanHaveAbstractDeclaration(classDescriptor)) { trace.report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, property.name ?: "", classDescriptor)) return } @@ -705,7 +705,7 @@ class DeclarationsChecker( if (containingDescriptor is ClassDescriptor) { val inInterface = containingDescriptor.kind == ClassKind.INTERFACE val isExpectClass = containingDescriptor.isExpect - if (hasAbstractModifier && !classCanHaveAbstractMembers(containingDescriptor)) { + if (hasAbstractModifier && !classCanHaveAbstractDeclaration(containingDescriptor)) { trace.report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(function, functionDescriptor.name.asString(), containingDescriptor)) } val hasBody = function.hasBody() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.kt index 6bb3c11548f..2584b35e0b7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.kt @@ -33,7 +33,7 @@ import org.jetbrains.kotlin.diagnostics.Errors.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers +import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractFakeOverride import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized import org.jetbrains.kotlin.types.* @@ -211,7 +211,7 @@ class OverrideResolver( } internal fun doReportErrors() { - val canHaveAbstractMembers = classCanHaveAbstractMembers(classDescriptor) + val canHaveAbstractMembers = classCanHaveAbstractFakeOverride(classDescriptor) if (abstractInBaseClassNoImpl.isNotEmpty() && !canHaveAbstractMembers) { trace.report(ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractInBaseClassNoImpl.first())) } diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.kt new file mode 100644 index 00000000000..5f8e04bd584 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.kt @@ -0,0 +1,28 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +interface Foo { + fun foo() +} + +expect class ImplicitFoo : Foo + +expect class ExplicitFoo : Foo { + override fun foo() +} + +expect class ImplicitFooCheck : Foo + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +actual class ImplicitFoo : Foo { + override fun foo() {} +} + +actual class ExplicitFoo : Foo { + actual override fun foo() {} +} + +actual class ImplicitFooCheck : Foo \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.txt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.txt new file mode 100644 index 00000000000..06fdcc25f1a --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.txt @@ -0,0 +1,65 @@ +// -- Module: -- +package + +public final expect class ExplicitFoo : Foo { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open expect override /*1*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface Foo { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final expect class ImplicitFoo : Foo { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final expect class ImplicitFooCheck : Foo { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + + +// -- Module: -- +package + +public final actual class ExplicitFoo : Foo { + public constructor ExplicitFoo() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open actual override /*1*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface Foo { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final actual class ImplicitFoo : Foo { + public constructor ImplicitFoo() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final actual class ImplicitFooCheck : Foo { + public constructor ImplicitFooCheck() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectClassWithExplicitAbstractMember.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectClassWithExplicitAbstractMember.kt new file mode 100644 index 00000000000..5297d35e3bc --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectClassWithExplicitAbstractMember.kt @@ -0,0 +1,23 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +interface Foo { + fun foo() +} + +expect class NonAbstractClass : Foo { + abstract fun bar() + + abstract val baz: Int + + abstract override fun foo() +} + +expect abstract class AbstractClass : Foo { + abstract fun bar() + + abstract val baz: Int + + abstract override fun foo() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectClassWithExplicitAbstractMember.txt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectClassWithExplicitAbstractMember.txt new file mode 100644 index 00000000000..21ce7a422b2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectClassWithExplicitAbstractMember.txt @@ -0,0 +1,26 @@ +package + +public abstract expect class AbstractClass : Foo { + public expect abstract val baz: kotlin.Int + public abstract expect fun bar(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract expect override /*1*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface Foo { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final expect class NonAbstractClass : Foo { + public expect abstract val baz: kotlin.Int + public abstract expect fun bar(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract expect override /*1*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.kt new file mode 100644 index 00000000000..b16a7251c1c --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.kt @@ -0,0 +1,36 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +expect abstract class Base { + abstract fun foo() +} + +expect class DerivedImplicit : Base + +expect class DerivedExplicit : Base { + override fun foo() +} + +expect class DerivedExplicitCheck : Base { + override fun foo() +} + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +actual abstract class Base { + actual abstract fun foo() +} + +actual class DerivedImplicit : Base() { + override fun foo() {} +} + +actual class DerivedExplicit : Base() { + actual override fun foo() {} +} + +actual class DerivedExplicitCheck : Base() { + override fun foo() {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.txt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.txt new file mode 100644 index 00000000000..9c8908e708b --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.txt @@ -0,0 +1,66 @@ +// -- Module: -- +package + +public abstract expect class Base { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract expect fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final expect class DerivedExplicit : Base { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open expect override /*1*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final expect class DerivedExplicitCheck : Base { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open expect override /*1*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final expect class DerivedImplicit : Base { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract expect override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + + +// -- Module: -- +package + +public abstract actual class Base { + public constructor Base() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract actual fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final actual class DerivedExplicit : Base { + public constructor DerivedExplicit() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open actual override /*1*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final actual class DerivedExplicitCheck : Base { + public constructor DerivedExplicitCheck() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final actual class DerivedImplicit : Base { + public constructor DerivedImplicit() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/multiplatform/explicitActualOnOverrideOfAbstractMethod/common.kt b/compiler/testData/multiplatform/explicitActualOnOverrideOfAbstractMethod/common.kt new file mode 100644 index 00000000000..12f11d20a7a --- /dev/null +++ b/compiler/testData/multiplatform/explicitActualOnOverrideOfAbstractMethod/common.kt @@ -0,0 +1,5 @@ +expect abstract class Base { + abstract fun foo() +} + +expect class DerivedImplicit : Base \ No newline at end of file diff --git a/compiler/testData/multiplatform/explicitActualOnOverrideOfAbstractMethod/jvm.kt b/compiler/testData/multiplatform/explicitActualOnOverrideOfAbstractMethod/jvm.kt new file mode 100644 index 00000000000..9899d7c14d9 --- /dev/null +++ b/compiler/testData/multiplatform/explicitActualOnOverrideOfAbstractMethod/jvm.kt @@ -0,0 +1,7 @@ +actual abstract class Base { + actual abstract fun foo() +} + +actual class DerivedImplicit : Base() { + override fun foo() {} +} \ No newline at end of file diff --git a/compiler/testData/multiplatform/explicitActualOnOverrideOfAbstractMethod/output.txt b/compiler/testData/multiplatform/explicitActualOnOverrideOfAbstractMethod/output.txt new file mode 100644 index 00000000000..b08950d503d --- /dev/null +++ b/compiler/testData/multiplatform/explicitActualOnOverrideOfAbstractMethod/output.txt @@ -0,0 +1,7 @@ +-- Common -- +Exit code: OK +Output: + +-- JVM -- +Exit code: OK +Output: diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index f8c054ea01c..a551a5683b8 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -14067,6 +14067,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("dontOverrideMethodsFromInterfaceInCommonCode.kt") + public void testDontOverrideMethodsFromInterfaceInCommonCode() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.kt"); + doTest(fileName); + } + + @TestMetadata("expectClassWithExplicitAbstractMember.kt") + public void testExpectClassWithExplicitAbstractMember() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/expectClassWithExplicitAbstractMember.kt"); + doTest(fileName); + } + @TestMetadata("expectClassWithoutConstructor.kt") public void testExpectClassWithoutConstructor() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/expectClassWithoutConstructor.kt"); @@ -14079,6 +14091,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("extendExpectedClassWithoutExplicitOverrideOfMethod.kt") + public void testExtendExpectedClassWithoutExplicitOverrideOfMethod() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.kt"); + doTest(fileName); + } + @TestMetadata("extraHeaderOnMembers.kt") public void testExtraHeaderOnMembers() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/extraHeaderOnMembers.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index d4bd9260aa3..d6d59197f5e 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -14067,6 +14067,18 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing doTest(fileName); } + @TestMetadata("dontOverrideMethodsFromInterfaceInCommonCode.kt") + public void testDontOverrideMethodsFromInterfaceInCommonCode() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.kt"); + doTest(fileName); + } + + @TestMetadata("expectClassWithExplicitAbstractMember.kt") + public void testExpectClassWithExplicitAbstractMember() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/expectClassWithExplicitAbstractMember.kt"); + doTest(fileName); + } + @TestMetadata("expectClassWithoutConstructor.kt") public void testExpectClassWithoutConstructor() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/expectClassWithoutConstructor.kt"); @@ -14079,6 +14091,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing doTest(fileName); } + @TestMetadata("extendExpectedClassWithoutExplicitOverrideOfMethod.kt") + public void testExtendExpectedClassWithoutExplicitOverrideOfMethod() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.kt"); + doTest(fileName); + } + @TestMetadata("extraHeaderOnMembers.kt") public void testExtraHeaderOnMembers() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/extraHeaderOnMembers.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java index 25207b58b49..96bd6b2e328 100644 --- a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java @@ -54,6 +54,12 @@ public class MultiPlatformIntegrationTestGenerated extends AbstractMultiPlatform doTest(fileName); } + @TestMetadata("explicitActualOnOverrideOfAbstractMethod") + public void testExplicitActualOnOverrideOfAbstractMethod() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/explicitActualOnOverrideOfAbstractMethod/"); + doTest(fileName); + } + @TestMetadata("genericDeclarations") public void testGenericDeclarations() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/genericDeclarations/"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java index 4ece325fe89..50a4d3c1716 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. + * Copyright 2010-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -458,7 +458,11 @@ public class DescriptorUtils { KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getAnyType(), type); } - public static boolean classCanHaveAbstractMembers(@NotNull ClassDescriptor classDescriptor) { + public static boolean classCanHaveAbstractFakeOverride(@NotNull ClassDescriptor classDescriptor) { + return classCanHaveAbstractDeclaration(classDescriptor) || classDescriptor.isExpect(); + } + + public static boolean classCanHaveAbstractDeclaration(@NotNull ClassDescriptor classDescriptor) { return classDescriptor.getModality() == Modality.ABSTRACT || isSealedClass(classDescriptor) || classDescriptor.getKind() == ClassKind.ENUM_CLASS; diff --git a/idea/testData/quickfix/override/dontOfferToImplementMembersForExpectedClass.kt b/idea/testData/quickfix/override/dontOfferToImplementMembersForExpectedClass.kt new file mode 100644 index 00000000000..e918eaca7dc --- /dev/null +++ b/idea/testData/quickfix/override/dontOfferToImplementMembersForExpectedClass.kt @@ -0,0 +1,12 @@ +// "Implement members" "false" +// ACTION: Create test +// ACTION: Make internal +// ACTION: Make private +// ACTION: Move 'A' to separate file + +interface I { + fun foo() +} + +@Suppress("UNSUPPORTED_FEATURE") +expect class A : I diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 938f6ecb797..d105bc89370 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -8072,6 +8072,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("dontOfferToImplementMembersForExpectedClass.kt") + public void testDontOfferToImplementMembersForExpectedClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/override/dontOfferToImplementMembersForExpectedClass.kt"); + doTest(fileName); + } + @TestMetadata("implemenAsConstructorParameter.kt") public void testImplemenAsConstructorParameter() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/override/implemenAsConstructorParameter.kt");