diff --git a/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash0.kt b/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash0.kt new file mode 100644 index 00000000000..96088333ab1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash0.kt @@ -0,0 +1,32 @@ +// FILE: A.java + +public interface A { + int field = 1; +} + +// FILE: B.java + +public interface B { + String field = 1; +} + +// FILE: E.java + +public class E implements A, B { +} + +// FILE: O.java + +public class O implements A, B { + public static double field = 1; +} + +// FILE: test.kt + +fun test() { + A.field + B.field + + E.field + O.field +} diff --git a/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash0.txt b/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash0.txt new file mode 100644 index 00000000000..72e351f10fe --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash0.txt @@ -0,0 +1,42 @@ +package + +public fun test(): kotlin.Unit + +public interface A { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public const final val field: kotlin.Int = 1 +} + +public interface B { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public const final val field: kotlin.String +} + +public open class E : A, B { + public constructor E() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public const final override /*1*/ /*fake_override*/ val field: kotlin.Int + public const final override /*1*/ /*fake_override*/ val field: kotlin.String +} + +public open class O : A, B { + public constructor O() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final override /*2*/ var field: kotlin.Double +} diff --git a/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash1.kt b/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash1.kt new file mode 100644 index 00000000000..bd332ebdb3c --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash1.kt @@ -0,0 +1,32 @@ +// FILE: A.java + +public interface A { + int field = 1; +} + +// FILE: B.java + +public interface B extends A { + String field = 1; +} + +// FILE: E.java + +public class E implements A, B { +} + +// FILE: O.java + +public class O implements A, B { + public static double field = 1; +} + +// FILE: test.kt + +fun test() { + A.field + B.field + + E.field + O.field +} diff --git a/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash1.txt b/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash1.txt new file mode 100644 index 00000000000..ac11490056b --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash1.txt @@ -0,0 +1,42 @@ +package + +public fun test(): kotlin.Unit + +public interface A { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public const final val field: kotlin.Int = 1 +} + +public interface B : A { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public const final override /*1*/ val field: kotlin.String +} + +public open class E : A, B { + public constructor E() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public const final override /*1*/ /*fake_override*/ val field: kotlin.Int + public const final override /*1*/ /*fake_override*/ val field: kotlin.String +} + +public open class O : A, B { + public constructor O() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final override /*2*/ var field: kotlin.Double +} diff --git a/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash2.kt b/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash2.kt new file mode 100644 index 00000000000..46996a8a01d --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash2.kt @@ -0,0 +1,66 @@ +// FILE: A.java + +public interface A { + int field = 1; +} + +// FILE: B.java + +public interface B { + String field = 1; +} + +// FILE: C.java + +public interface C extends A { +} + +// FILE: D.java + +public interface D extends B { +} + +// FILE: E.java + +public class E implements C, D { +} + +// FILE: EE.java + +public class EE extends E { +} + +// FILE: EO.java + +public class EO extends E { + public static double field = 1; +} + +// FILE: O.java + +public class O implements C, D { + public static double field = 1; +} + +// FILE: OO.java + +public class OO extends O { +} + +// FILE: test.kt + +fun test() { + A.field + B.field + + C.field + D.field + + E.field + O.field + + EE.field + EO.field + + OO.field +} diff --git a/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash2.txt b/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash2.txt new file mode 100644 index 00000000000..4c1fbf3bfa2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash2.txt @@ -0,0 +1,91 @@ +package + +public fun test(): kotlin.Unit + +public interface A { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public const final val field: kotlin.Int = 1 +} + +public interface B { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public const final val field: kotlin.String +} + +public interface C : A { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public const final override /*1*/ /*fake_override*/ val field: kotlin.Int +} + +public interface D : B { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public const final override /*1*/ /*fake_override*/ val field: kotlin.String +} + +public open class E : C, D { + public constructor E() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public const final override /*1*/ /*fake_override*/ val field: kotlin.Int + public const final override /*1*/ /*fake_override*/ val field: kotlin.String +} + +public open class EE : E { + public constructor EE() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public const final override /*1*/ /*fake_override*/ val field: kotlin.Int + public const final override /*1*/ /*fake_override*/ val field: kotlin.String +} + +public open class EO : E { + public constructor EO() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final override /*2*/ var field: kotlin.Double +} + +public open class O : C, D { + public constructor O() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final override /*2*/ var field: kotlin.Double +} + +public open class OO : O { + public constructor OO() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final override /*1*/ /*fake_override*/ var field: kotlin.Double +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 863de548140..f2d241e6e10 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -12934,6 +12934,24 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("nameClash0.kt") + public void testNameClash0() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash0.kt"); + doTest(fileName); + } + + @TestMetadata("nameClash1.kt") + public void testNameClash1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash1.kt"); + doTest(fileName); + } + + @TestMetadata("nameClash2.kt") + public void testNameClash2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/inheritance/statics/nameClash2.kt"); + doTest(fileName); + } + @TestMetadata("oneInterfaceManyTimes.kt") public void testOneInterfaceManyTimes() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/inheritance/statics/oneInterfaceManyTimes.kt"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaStaticClassScope.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaStaticClassScope.kt index f8f1c8a3205..dc8e465f9bc 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaStaticClassScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaStaticClassScope.kt @@ -85,7 +85,20 @@ public class LazyJavaStaticClassScope( override fun computeNonDeclaredProperties(name: Name, result: MutableCollection) { val propertiesFromSupertypes = getStaticPropertiesFromJavaSupertypes(name, getContainingDeclaration()) - result.addAll(DescriptorResolverUtils.resolveOverrides(name, propertiesFromSupertypes, result, getContainingDeclaration(), c.components.errorReporter)) + + val actualProperties = + if (!result.isEmpty()) { + DescriptorResolverUtils.resolveOverrides(name, propertiesFromSupertypes, result, getContainingDeclaration(), c.components.errorReporter) + } + else { + propertiesFromSupertypes.groupBy { + it.realOriginal + }.flatMap { + DescriptorResolverUtils.resolveOverrides(name, it.value, result, getContainingDeclaration(), c.components.errorReporter) + } + } + + result.addAll(actualProperties) } override fun getContainingDeclaration() = super.getContainingDeclaration() as LazyJavaClassDescriptor @@ -114,4 +127,11 @@ public class LazyJavaStaticClassScope( return descriptor.typeConstructor.supertypes.flatMap(::getStaticProperties).toSet() } + + private val PropertyDescriptor.realOriginal: PropertyDescriptor + get() { + if (this.kind.isReal) return this + + return this.overriddenDescriptors.map { it.realOriginal }.distinct().single() + } }