From 56d4ff0cad88daabf0aa6ec229b78400cf7e4422 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 15 Dec 2016 16:28:02 +0300 Subject: [PATCH] Support nested header/impl classes --- .../checkers/HeaderImplDeclarationChecker.kt | 34 ++++- .../lazy/descriptors/LazyClassMemberScope.kt | 11 +- .../multiplatform/headerClass/classKinds.txt | 1 - .../headerClass/nestedClasses.kt | 46 ++++++ .../headerClass/nestedClasses.txt | 142 ++++++++++++++++++ .../generic}/common.kt | 0 .../generic}/jvm.kt | 0 .../generic}/output.txt | 2 +- .../nestedClassesViaTypeAlias/common.kt | 3 + .../nestedClassesViaTypeAlias/jvm.kt | 5 + .../nestedClassesViaTypeAlias/output.txt | 10 ++ .../incompatibleNestedClasses/common.kt | 19 +++ .../incompatibleNestedClasses/jvm.kt | 19 +++ .../incompatibleNestedClasses/output.txt | 80 ++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 + ...MultiPlatformIntegrationTestGenerated.java | 34 ++++- .../kotlin/resolve/DescriptorUtils.kt | 4 +- 17 files changed, 393 insertions(+), 23 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClasses.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClasses.txt rename compiler/testData/multiplatform/{implementClassWithTypeAlias => implTypeAlias/generic}/common.kt (100%) rename compiler/testData/multiplatform/{implementClassWithTypeAlias => implTypeAlias/generic}/jvm.kt (100%) rename compiler/testData/multiplatform/{implementClassWithTypeAlias => implTypeAlias/generic}/output.txt (51%) create mode 100644 compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/common.kt create mode 100644 compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/jvm.kt create mode 100644 compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/output.txt create mode 100644 compiler/testData/multiplatform/incompatibleNestedClasses/common.kt create mode 100644 compiler/testData/multiplatform/incompatibleNestedClasses/jvm.kt create mode 100644 compiler/testData/multiplatform/incompatibleNestedClasses/output.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt index f530a57b4e7..ae332f874f0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt @@ -31,7 +31,7 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker.Compatibility.Compatible import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker.Compatibility.Incompatible -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter @@ -101,7 +101,7 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null) private fun checkImplementationHasHeaderDeclaration( reportOn: KtDeclaration, descriptor: MemberDescriptor, diagnosticHolder: DiagnosticSink ) { - fun ClassifierDescriptor.findDeclarationForClass(): ClassDescriptor? = + fun ClassifierDescriptorWithTypeParameters.findDeclarationForClass(): ClassDescriptor? = findClassifiersFromTheSameModule().firstOrNull { declaration -> this != declaration && declaration is ClassDescriptor && declaration.isHeader && @@ -122,7 +122,7 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null) areCompatibleCallables(declaration, descriptor, checkImpl = false) == Compatible } } - is ClassifierDescriptor -> descriptor.findDeclarationForClass() != null + is ClassifierDescriptorWithTypeParameters -> descriptor.findDeclarationForClass() != null else -> false } @@ -146,12 +146,26 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null) } } - fun ClassifierDescriptor.findClassifiersFromTheSameModule(): Collection { + fun ClassifierDescriptorWithTypeParameters.findClassifiersFromTheSameModule(): Collection { val myModule = moduleToCheck ?: module - // TODO: support nested classes - return myModule.getPackage(fqNameSafe.parent()).memberScope - .getDescriptorsFiltered(DescriptorKindFilter.CLASSIFIERS) { it == name } - .filterIsInstance() + val classId = classId ?: return emptyList() + + fun MemberScope.getAllClassifiers(name: Name): Collection = + getDescriptorsFiltered(DescriptorKindFilter.CLASSIFIERS) { it == name } + .filterIsInstance() + + val segments = classId.relativeClassName.pathSegments() + var classifiers = myModule.getPackage(classId.packageFqName).memberScope.getAllClassifiers(segments.first()) + + for (name in segments.subList(1, segments.size)) { + classifiers = classifiers.mapNotNull { classifier -> + (classifier as? ClassDescriptor)?.unsubstitutedInnerClassesScope?.getContributedClassifier( + name, NoLookupLocation.FOR_ALREADY_TRACKED + ) as? ClassifierDescriptorWithTypeParameters + } + } + + return classifiers } sealed class Compatibility { @@ -190,6 +204,8 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null) object ClassKind : Incompatible("class kinds are different (class, interface, object, enum, annotation)") + object ClassModifiers : Incompatible("modifiers are different (companion, inner)") + object Supertypes : Incompatible("some supertypes are missing in the implementation") class ClassScopes( @@ -318,6 +334,8 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null) if (a.kind != b.kind) return Incompatible.ClassKind + if (!equalBy(a, b) { listOf(it.isCompanionObject, it.isInner) }) return Incompatible.ClassModifiers + val aTypeParams = a.declaredTypeParameters val bTypeParams = b.declaredTypeParameters if (aTypeParams.size != bTypeParams.size) return Incompatible.TypeParameterCount diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt index dc97543a794..5f7cbf5fd00 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt @@ -336,6 +336,8 @@ open class LazyClassMemberScope( val hasPrimaryConstructor = classOrObject.hasExplicitPrimaryConstructor() if (DescriptorUtils.isInterface(thisDescriptor) && !hasPrimaryConstructor) return null + if (thisDescriptor.isHeader && thisDescriptor.kind == ClassKind.OBJECT) return null + if (DescriptorUtils.canHaveDeclaredConstructors(thisDescriptor) || hasPrimaryConstructor) { val constructor = c.functionDescriptorResolver.resolvePrimaryConstructorDescriptor( thisDescriptor.scopeForConstructorHeaderResolution, thisDescriptor, classOrObject, trace) @@ -343,11 +345,10 @@ open class LazyClassMemberScope( setDeferredReturnType(constructor) return constructor } - else { - val constructor = DescriptorResolver.createAndRecordPrimaryConstructorForObject(classOrObject, thisDescriptor, trace) - setDeferredReturnType(constructor) - return constructor - } + + val constructor = DescriptorResolver.createAndRecordPrimaryConstructorForObject(classOrObject, thisDescriptor, trace) + setDeferredReturnType(constructor) + return constructor } private fun resolveSecondaryConstructors(): Collection { diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/classKinds.txt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/classKinds.txt index 937f3d335aa..eff3813dda0 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/classKinds.txt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/classKinds.txt @@ -40,7 +40,6 @@ public header interface Interface { } public header object Object { - private constructor Object() 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 diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClasses.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClasses.kt new file mode 100644 index 00000000000..1e247b58d61 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClasses.kt @@ -0,0 +1,46 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +header class OuterClass { + header class NestedClass { + header class DeepNested { + header class Another + } + } + + header inner class InnerClass + + header companion object +} + +header class OuterClassWithNamedCompanion { + header companion object Factory +} + +header object OuterObject { + header object NestedObject +} + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +impl class OuterClass { + impl class NestedClass { + impl class DeepNested { + impl class Another + } + } + + impl inner class InnerClass + + impl companion object +} + +impl class OuterClassWithNamedCompanion { + impl companion object Factory +} + +impl object OuterObject { + impl object NestedObject +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClasses.txt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClasses.txt new file mode 100644 index 00000000000..d4507fbf8f9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClasses.txt @@ -0,0 +1,142 @@ +// -- Module: -- +package + +public final header class OuterClass { + public constructor OuterClass() + 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 + + public header companion object Companion { + 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 + } + + public final header inner class InnerClass { + public constructor InnerClass() + 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 + } + + public final header class NestedClass { + public constructor NestedClass() + 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 + + public final header class DeepNested { + public constructor DeepNested() + 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 + + public final header class Another { + public constructor Another() + 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 + } + } + } +} + +public final header class OuterClassWithNamedCompanion { + public constructor OuterClassWithNamedCompanion() + 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 + + public header companion object Factory { + 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 + } +} + +public header object OuterObject { + 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 + + public header object NestedObject { + 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 + } +} + + +// -- Module: -- +package + +public final impl class OuterClass { + public constructor OuterClass() + 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 + + public impl companion object Companion { + private constructor Companion() + 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 + } + + public final impl inner class InnerClass { + public constructor InnerClass() + 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 + } + + public final impl class NestedClass { + public constructor NestedClass() + 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 + + public final impl class DeepNested { + public constructor DeepNested() + 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 + + public final impl class Another { + public constructor Another() + 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 + } + } + } +} + +public final impl class OuterClassWithNamedCompanion { + public constructor OuterClassWithNamedCompanion() + 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 + + public impl companion object Factory { + private constructor Factory() + 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 + } +} + +public impl object OuterObject { + private constructor OuterObject() + 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 + + public impl object NestedObject { + private constructor NestedObject() + 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 + } +} diff --git a/compiler/testData/multiplatform/implementClassWithTypeAlias/common.kt b/compiler/testData/multiplatform/implTypeAlias/generic/common.kt similarity index 100% rename from compiler/testData/multiplatform/implementClassWithTypeAlias/common.kt rename to compiler/testData/multiplatform/implTypeAlias/generic/common.kt diff --git a/compiler/testData/multiplatform/implementClassWithTypeAlias/jvm.kt b/compiler/testData/multiplatform/implTypeAlias/generic/jvm.kt similarity index 100% rename from compiler/testData/multiplatform/implementClassWithTypeAlias/jvm.kt rename to compiler/testData/multiplatform/implTypeAlias/generic/jvm.kt diff --git a/compiler/testData/multiplatform/implementClassWithTypeAlias/output.txt b/compiler/testData/multiplatform/implTypeAlias/generic/output.txt similarity index 51% rename from compiler/testData/multiplatform/implementClassWithTypeAlias/output.txt rename to compiler/testData/multiplatform/implTypeAlias/generic/output.txt index f12f8c5d70d..20ef6bcbadd 100644 --- a/compiler/testData/multiplatform/implementClassWithTypeAlias/output.txt +++ b/compiler/testData/multiplatform/implTypeAlias/generic/output.txt @@ -5,7 +5,7 @@ Output: -- JVM -- Exit code: OK Output: -compiler/testData/multiplatform/implementClassWithTypeAlias/jvm.kt:3:13: warning: parameter 'a' is never used +compiler/testData/multiplatform/implTypeAlias/generic/jvm.kt:3:13: warning: parameter 'a' is never used fun foo(a: A): List? = null ^ diff --git a/compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/common.kt b/compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/common.kt new file mode 100644 index 00000000000..6ab70aa0599 --- /dev/null +++ b/compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/common.kt @@ -0,0 +1,3 @@ +header class ByTypeAlias { + header interface Nested +} diff --git a/compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/jvm.kt b/compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/jvm.kt new file mode 100644 index 00000000000..5e28bc060d5 --- /dev/null +++ b/compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/jvm.kt @@ -0,0 +1,5 @@ +class ByTypeAliasImpl { + interface Nested +} + +impl typealias ByTypeAlias = ByTypeAliasImpl diff --git a/compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/output.txt b/compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/output.txt new file mode 100644 index 00000000000..ef8784d01ee --- /dev/null +++ b/compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/output.txt @@ -0,0 +1,10 @@ +-- Common -- +Exit code: OK +Output: + +-- JVM -- +Exit code: COMPILATION_ERROR +Output: +compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/common.kt:2:22: error: header declaration 'Nested' has no implementation in module + header interface Nested + ^ diff --git a/compiler/testData/multiplatform/incompatibleNestedClasses/common.kt b/compiler/testData/multiplatform/incompatibleNestedClasses/common.kt new file mode 100644 index 00000000000..0e2231f7e08 --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleNestedClasses/common.kt @@ -0,0 +1,19 @@ +header class O1 { + header class N1 + header interface N2 + header object N3 +} + +header class O2 { + header class N2 + header inner class I2 +} + +header class O3 { + header object Companion + header companion object Factory +} + +header class O4 { + header companion object +} diff --git a/compiler/testData/multiplatform/incompatibleNestedClasses/jvm.kt b/compiler/testData/multiplatform/incompatibleNestedClasses/jvm.kt new file mode 100644 index 00000000000..30f96386ac6 --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleNestedClasses/jvm.kt @@ -0,0 +1,19 @@ +impl class O1 { + impl interface N1 + impl object N2 + impl class N3 +} + +impl class O2 { + impl inner class N2 + impl class I2 +} + +impl class O3 { + impl companion object {} + impl object Factory +} + +impl class O4 { + impl object Companion +} diff --git a/compiler/testData/multiplatform/incompatibleNestedClasses/output.txt b/compiler/testData/multiplatform/incompatibleNestedClasses/output.txt new file mode 100644 index 00000000000..ec4e2d79e68 --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleNestedClasses/output.txt @@ -0,0 +1,80 @@ +-- Common -- +Exit code: OK +Output: + +-- JVM -- +Exit code: COMPILATION_ERROR +Output: +compiler/testData/multiplatform/incompatibleNestedClasses/common.kt:2:18: error: header declaration 'N1' has no implementation in module +The following declaration is incompatible because class kinds are different (class, interface, object, enum, annotation): + public impl interface N1 + + header class N1 + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/common.kt:3:22: error: header declaration 'N2' has no implementation in module +The following declaration is incompatible because class kinds are different (class, interface, object, enum, annotation): + public impl object N2 + + header interface N2 + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/common.kt:4:12: error: header declaration 'N3' has no implementation in module +The following declaration is incompatible because class kinds are different (class, interface, object, enum, annotation): + public final impl class N3 + + header object N3 + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/common.kt:8:18: error: header declaration 'N2' has no implementation in module +The following declaration is incompatible because modifiers are different (companion, inner): + public final impl inner class N2 + + header class N2 + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/common.kt:9:24: error: header declaration 'I2' has no implementation in module +The following declaration is incompatible because modifiers are different (companion, inner): + public final impl class I2 + + header inner class I2 + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/common.kt:13:12: error: header declaration 'Companion' has no implementation in module +The following declaration is incompatible because modifiers are different (companion, inner): + public impl companion object + + header object Companion + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/common.kt:14:22: error: header declaration 'Factory' has no implementation in module +The following declaration is incompatible because modifiers are different (companion, inner): + public impl object Factory + + header companion object Factory + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/common.kt:18:22: error: header declaration 'Companion' has no implementation in module +The following declaration is incompatible because modifiers are different (companion, inner): + public impl object Companion + + header companion object + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/jvm.kt:2:5: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code + impl interface N1 + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/jvm.kt:3:5: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code + impl object N2 + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/jvm.kt:4:5: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code + impl class N3 + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/jvm.kt:8:5: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code + impl inner class N2 + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/jvm.kt:9:5: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code + impl class I2 + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/jvm.kt:13:5: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code + impl companion object {} + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/jvm.kt:14:5: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code + impl object Factory + ^ +compiler/testData/multiplatform/incompatibleNestedClasses/jvm.kt:18:5: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code + impl object Companion + ^ + diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index ec67739ea9c..4f4ef4195a5 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -13104,6 +13104,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("nestedClasses.kt") + public void testNestedClasses() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClasses.kt"); + doTest(fileName); + } + @TestMetadata("simpleHeaderClass.kt") public void testSimpleHeaderClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/simpleHeaderClass.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java index b44efed9dc9..63194701dcb 100644 --- a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java @@ -42,12 +42,6 @@ public class MultiPlatformIntegrationTestGenerated extends AbstractMultiPlatform doTest(fileName); } - @TestMetadata("implementClassWithTypeAlias") - public void testImplementClassWithTypeAlias() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/implementClassWithTypeAlias/"); - doTest(fileName); - } - @TestMetadata("incompatibleCallables") public void testIncompatibleCallables() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/incompatibleCallables/"); @@ -66,6 +60,12 @@ public class MultiPlatformIntegrationTestGenerated extends AbstractMultiPlatform doTest(fileName); } + @TestMetadata("incompatibleNestedClasses") + public void testIncompatibleNestedClasses() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/incompatibleNestedClasses/"); + doTest(fileName); + } + @TestMetadata("incompatibleProperties") public void testIncompatibleProperties() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/incompatibleProperties/"); @@ -130,4 +130,26 @@ public class MultiPlatformIntegrationTestGenerated extends AbstractMultiPlatform } + @TestMetadata("compiler/testData/multiplatform/implTypeAlias") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ImplTypeAlias extends AbstractMultiPlatformIntegrationTest { + public void testAllFilesPresentInImplTypeAlias() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/multiplatform/implTypeAlias"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true); + } + + @TestMetadata("generic") + public void testGeneric() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/implTypeAlias/generic/"); + doTest(fileName); + } + + @TestMetadata("nestedClassesViaTypeAlias") + public void testNestedClassesViaTypeAlias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/implTypeAlias/nestedClassesViaTypeAlias/"); + doTest(fileName); + } + + } + } diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt index 5d303e716e6..7084798ca25 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt @@ -74,11 +74,11 @@ val ClassifierDescriptorWithTypeParameters.denotedClassDescriptor: ClassDescript else -> throw UnsupportedOperationException("Unexpected descriptor kind: $this") } -val ClassDescriptor.classId: ClassId? +val ClassifierDescriptorWithTypeParameters.classId: ClassId? get() = containingDeclaration.let { owner -> when (owner) { is PackageFragmentDescriptor -> ClassId(owner.fqName, name) - is ClassDescriptor -> owner.classId?.createNestedClassId(name) + is ClassifierDescriptorWithTypeParameters -> owner.classId?.createNestedClassId(name) else -> null } }