diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 5fc6948ca6d..afc6b762222 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -25710,6 +25710,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/scopes/classHeader/classParents.kt"); } + @Test + @TestMetadata("companionNestedVsOuter.kt") + public void testCompanionNestedVsOuter() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/classHeader/companionNestedVsOuter.kt"); + } + @Test @TestMetadata("companionObjectParents.kt") public void testCompanionObjectParents() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 134eebd47fe..b8510243966 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -25710,6 +25710,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/scopes/classHeader/classParents.kt"); } + @Test + @TestMetadata("companionNestedVsOuter.kt") + public void testCompanionNestedVsOuter() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/classHeader/companionNestedVsOuter.kt"); + } + @Test @TestMetadata("companionObjectParents.kt") public void testCompanionObjectParents() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index 85df3275aa7..7d292ba95cb 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -25710,6 +25710,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/scopes/classHeader/classParents.kt"); } + @Test + @TestMetadata("companionNestedVsOuter.kt") + public void testCompanionNestedVsOuter() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/classHeader/companionNestedVsOuter.kt"); + } + @Test @TestMetadata("companionObjectParents.kt") public void testCompanionObjectParents() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt index 6294198745b..7e74549d4cd 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt @@ -24,7 +24,6 @@ import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeTypeParameterSupertype import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.LocalClassesNavigationInfo -import org.jetbrains.kotlin.fir.scopes.FirCompositeScope import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.createImportingScopes import org.jetbrains.kotlin.fir.scopes.getNestedClassifierScope @@ -43,6 +42,7 @@ import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.types.model.TypeArgumentMarker import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.kotlin.utils.addToStdlib.safeAs class FirSupertypeResolverProcessor(session: FirSession, scopeSession: ScopeSession) : FirTransformerBasedResolveProcessor(session, scopeSession) { @@ -169,19 +169,22 @@ private fun FirClassLikeDeclaration.typeParametersScope(): FirScope? { return FirMemberTypeParameterScope(this) } -private fun createOtherScopesForNestedClasses( +private fun createOtherScopesForNestedClassesOrCompanion( klass: FirClass, session: FirSession, scopeSession: ScopeSession, - supertypeComputationSession: SupertypeComputationSession + supertypeComputationSession: SupertypeComputationSession, + withCompanionScopes: Boolean, ): Collection = mutableListOf().apply { // Note: from higher priority to lower priority // See also: BodyResolveContext.withScopesForClass addIfNotNull(session.nestedClassifierScope(klass)) - val companionObjects = klass.declarations.filterIsInstance().filter { it.isCompanion } - for (companionObject in companionObjects) { - addIfNotNull(session.nestedClassifierScope(companionObject)) + if (withCompanionScopes) { + val companionObjects = klass.declarations.filterIsInstance().filter { it.isCompanion } + for (companionObject in companionObjects) { + addIfNotNull(session.nestedClassifierScope(companionObject)) + } } lookupSuperTypes( klass, @@ -240,13 +243,26 @@ open class FirSupertypeResolverVisitor( private fun prepareScopeForNestedClasses(klass: FirClass): ScopePersistentList { return supertypeComputationSession.getOrPutScopeForNestedClasses(klass) { - val scopes = prepareScopes(klass) - - resolveAllSupertypes(klass, klass.superTypeRefs) - scopes.pushAll(createOtherScopesForNestedClasses(klass, session, scopeSession, supertypeComputationSession)) + calculateScopes(klass, true) } } + private fun prepareScopeForCompanion(klass: FirClass): ScopePersistentList { + return supertypeComputationSession.getOrPutScopeForCompanion(klass) { + calculateScopes(klass, false) + } + } + + private fun calculateScopes( + klass: FirClass, + withCompanionScopes: Boolean, + ): PersistentList { + resolveAllSupertypes(klass, klass.superTypeRefs) + return prepareScopes(klass).pushAll( + createOtherScopesForNestedClassesOrCompanion(klass, session, scopeSession, supertypeComputationSession, withCompanionScopes) + ) + } + private fun resolveAllSupertypes( classLikeDeclaration: FirClassLikeDeclaration, supertypeRefs: List, @@ -285,6 +301,10 @@ open class FirSupertypeResolverVisitor( else -> scopeForLocalClass ?: return persistentListOf() } } + classLikeDeclaration.safeAs()?.isCompanion == true -> { + val outerClassFir = classId.outerClassId?.let(::getFirClassifierByFqName) as? FirRegularClass + prepareScopeForCompanion(outerClassFir ?: return persistentListOf()) + } classId.isNestedClass -> { val outerClassFir = classId.outerClassId?.let(::getFirClassifierByFqName) as? FirRegularClass prepareScopeForNestedClasses(outerClassFir ?: return persistentListOf()) @@ -446,6 +466,7 @@ private fun createErrorTypeRef(fir: FirElement, message: String, kind: Diagnosti class SupertypeComputationSession { private val fileScopesMap = hashMapOf() private val scopesForNestedClassesMap = hashMapOf() + private val scopesForCompanionMap = hashMapOf() val supertypeStatusMap = linkedMapOf() val supertypesSupplier: SupertypeSupplier = object : SupertypeSupplier() { @@ -473,6 +494,9 @@ class SupertypeComputationSession { fun getOrPutScopeForNestedClasses(klass: FirClass, scope: () -> ScopePersistentList): ScopePersistentList = scopesForNestedClassesMap.getOrPut(klass) { scope() } + fun getOrPutScopeForCompanion(klass: FirClass, scope: () -> ScopePersistentList): ScopePersistentList = + scopesForCompanionMap.getOrPut(klass) { scope() } + fun startComputingSupertypes(classLikeDeclaration: FirClassLikeDeclaration) { require(supertypeStatusMap[classLikeDeclaration] == null) { "Unexpected in startComputingSupertypes supertype status for $classLikeDeclaration: ${supertypeStatusMap[classLikeDeclaration]}" diff --git a/compiler/testData/diagnostics/tests/scopes/classHeader/companionNestedVsOuter.kt b/compiler/testData/diagnostics/tests/scopes/classHeader/companionNestedVsOuter.kt new file mode 100644 index 00000000000..2750d2c0992 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/classHeader/companionNestedVsOuter.kt @@ -0,0 +1,8 @@ +// FIR_IDENTICAL +open class B + +class A { + companion object : B() { // Nested B should be invisible here but it's not + class B + } +} diff --git a/compiler/testData/diagnostics/tests/scopes/classHeader/companionNestedVsOuter.txt b/compiler/testData/diagnostics/tests/scopes/classHeader/companionNestedVsOuter.txt new file mode 100644 index 00000000000..660fe30d293 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/classHeader/companionNestedVsOuter.txt @@ -0,0 +1,29 @@ +package + +public final class A { + public constructor 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 + + public companion object Companion : B { + 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 class B { + public constructor 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 + } + } +} + +public open class B { + public constructor 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 +} diff --git a/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.fir.kt b/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.fir.kt index 6c0fe35fb82..bdc1812e43c 100644 --- a/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.fir.kt @@ -7,7 +7,7 @@ val bImpl: B.Companion.Interface get() = null!! interface A { - companion object : Nested(), Interface by aImpl, I { + companion object : Nested(), Interface by aImpl, I<Nested, Interface> { class Nested @@ -16,7 +16,7 @@ interface A { } class B { - companion object : Nested(), Interface by aImpl, I { + companion object : Nested(), Interface by aImpl, I<Nested, Interface> { class Nested diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index b16c76b5eda..8979e789739 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -25722,6 +25722,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/scopes/classHeader/classParents.kt"); } + @Test + @TestMetadata("companionNestedVsOuter.kt") + public void testCompanionNestedVsOuter() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/classHeader/companionNestedVsOuter.kt"); + } + @Test @TestMetadata("companionObjectParents.kt") public void testCompanionObjectParents() throws Exception {