From 7d793f6750404b439cca8af813d114c63c0c6a85 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 18 Apr 2019 11:28:13 +0300 Subject: [PATCH] FIR resolve: add handling of companions as objects --- .../fir/java/declarations/FirJavaClass.kt | 3 ++ .../kotlin/fir/builder/RawFirBuilder.kt | 14 ++++--- .../deserialization/ClassDeserialization.kt | 18 +++++--- .../kotlin/fir/resolve/ScopeUtils.kt | 5 ++- .../resolve/expresssions/companion.kt | 21 ++++++++++ .../resolve/expresssions/companion.txt | 42 +++++++++++++++++++ .../testData/resolve/fromBuilder/enums.txt | 2 +- .../fir/FirResolveTestCaseGenerated.java | 5 +++ .../fir/declarations/FirRegularClass.kt | 2 + .../fir/declarations/impl/FirClassImpl.kt | 14 +++++++ 10 files changed, 113 insertions(+), 13 deletions(-) create mode 100644 compiler/fir/resolve/testData/resolve/expresssions/companion.kt create mode 100644 compiler/fir/resolve/testData/resolve/expresssions/companion.txt diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt index bd391c6cbae..da4d2003ce0 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt @@ -43,6 +43,9 @@ class FirJavaClass( override val declarations = mutableListOf() + override val companionObject: FirRegularClass? + get() = null + override fun replaceSupertypes(newSupertypes: List): FirRegularClass { superTypeRefs.clear() superTypeRefs.addAll(newSupertypes) diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 19df93df401..c3fa4fc5466 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -469,8 +469,10 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { val delegatedSelfType = enumEntry.toDelegatedSelfType(firEnumEntry) val delegatedSuperType = enumEntry.extractSuperTypeListEntriesTo(firEnumEntry, delegatedSelfType) for (declaration in enumEntry.declarations) { - firEnumEntry.declarations += declaration.toFirDeclaration( - delegatedSuperType, delegatedSelfType, enumEntry, hasPrimaryConstructor = true + firEnumEntry.addDeclaration( + declaration.toFirDeclaration( + delegatedSuperType, delegatedSelfType, enumEntry, hasPrimaryConstructor = true + ) ) } firEnumEntry @@ -536,14 +538,16 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { if (primaryConstructor != null && firPrimaryConstructor != null) { primaryConstructor.valueParameters.zip(firPrimaryConstructor.valueParameters).forEach { (ktParameter, firParameter) -> if (ktParameter.hasValOrVar()) { - firClass.declarations += ktParameter.toFirProperty(firParameter) + firClass.addDeclaration(ktParameter.toFirProperty(firParameter)) } } } for (declaration in classOrObject.declarations) { - firClass.declarations += declaration.toFirDeclaration( - delegatedSuperType, delegatedSelfType, classOrObject, hasPrimaryConstructor = primaryConstructor != null + firClass.addDeclaration( + declaration.toFirDeclaration( + delegatedSuperType, delegatedSelfType, classOrObject, hasPrimaryConstructor = primaryConstructor != null + ) ) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt index 571242fae83..1e6a8f80d6f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt @@ -64,7 +64,7 @@ fun deserializeClassToSymbol( } // TODO: properties - declarations += classProto.functionList.map(classDeserializer::loadFunction) + addDeclarations(classProto.functionList.map(classDeserializer::loadFunction)) val delegatedSelfType = FirResolvedTypeRefImpl( session, @@ -77,12 +77,18 @@ fun deserializeClassToSymbol( isMarkedNullable = false, annotations = emptyList() ) - declarations += classProto.constructorList.map { classDeserializer.loadConstructor(it, delegatedSelfType) } + addDeclarations( + classProto.constructorList.map { + classDeserializer.loadConstructor(it, delegatedSelfType) + } + ) - declarations += classProto.nestedClassNameList.mapNotNull { nestedNameId -> - val nestedClassId = classId.createNestedClassId(Name.identifier(nameResolver.getString(nestedNameId))) - deserializeNestedClass(nestedClassId, context)?.fir - } + addDeclarations( + classProto.nestedClassNameList.mapNotNull { nestedNameId -> + val nestedClassId = classId.createNestedClassId(Name.identifier(nameResolver.getString(nestedNameId))) + deserializeNestedClass(nestedClassId, context)?.fir + } + ) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt index d6798d3953a..9cff9ef75e8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt @@ -29,7 +29,10 @@ fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession) // For ConeClassLikeType they might be a type alias instead of a regular class // TODO: support that case and switch back to `firUnsafe` instead of `firSafeNullable` val fir = this.lookupTag.toSymbol(useSiteSession)?.firSafeNullable() ?: return null - wrapSubstitutionScopeIfNeed(useSiteSession, fir.buildUseSiteScope(useSiteSession, scopeSession), scopeSession) + val companionScope = fir.companionObject?.buildUseSiteScope(useSiteSession, scopeSession) + val ownScope = wrapSubstitutionScopeIfNeed(useSiteSession, fir.buildUseSiteScope(useSiteSession, scopeSession), scopeSession) + if (companionScope != null) FirCompositeScope(mutableListOf(ownScope, companionScope)) else ownScope + } is ConeTypeParameterType -> { // TODO: support LibraryTypeParameterSymbol or get rid of it diff --git a/compiler/fir/resolve/testData/resolve/expresssions/companion.kt b/compiler/fir/resolve/testData/resolve/expresssions/companion.kt new file mode 100644 index 00000000000..2127b175c0e --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/expresssions/companion.kt @@ -0,0 +1,21 @@ +open class A { + companion object { + fun foo() {} + } + + fun bar() { + foo() + } +} + +class B { + companion object : A() { + fun baz() {} + } +} + +fun test() { + A.foo() + B.bar() + B.baz() +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/expresssions/companion.txt b/compiler/fir/resolve/testData/resolve/expresssions/companion.txt new file mode 100644 index 00000000000..9560f3ab96c --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/expresssions/companion.txt @@ -0,0 +1,42 @@ +FILE: companion.kt + public open class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + public final companion object Companion : R|kotlin/Any| { + private constructor(): R|A.Companion| { + super() + } + + public final fun foo(): R|kotlin/Unit| { + } + + } + + public final fun bar(): R|kotlin/Unit| { + R|/A.Companion.foo|() + } + + } + public final class B : R|kotlin/Any| { + public constructor(): R|B| { + super() + } + + public final companion object Companion : R|A| { + private constructor(): R|B.Companion| { + super() + } + + public final fun baz(): R|kotlin/Unit| { + } + + } + + } + public final fun test(): R|kotlin/Unit| { + R|/A|.R|/A.Companion.foo|() + R|/B|.#() + R|/B|.R|/B.Companion.baz|() + } diff --git a/compiler/fir/resolve/testData/resolve/fromBuilder/enums.txt b/compiler/fir/resolve/testData/resolve/fromBuilder/enums.txt index 0c2b61c5176..a6b85945550 100644 --- a/compiler/fir/resolve/testData/resolve/fromBuilder/enums.txt +++ b/compiler/fir/resolve/testData/resolve/fromBuilder/enums.txt @@ -70,7 +70,7 @@ FILE: enums.kt } - public final val g: R|kotlin/Double| = #.#(R|/Planet.m|).#(R|/Planet.r|.R|kotlin/Double.times|(R|/Planet.r|)) + public final val g: R|kotlin/Double| = R|/Planet.Companion.G|.R|kotlin/Double.times|(R|/Planet.m|).R|kotlin/Double.div|(R|/Planet.r|.R|kotlin/Double.times|(R|/Planet.r|)) public get(): R|kotlin/Double| public abstract fun sayHello(): R|kotlin/Unit| diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java index c0e38b21d50..4329d1add9a 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java @@ -202,6 +202,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase { runTest("compiler/fir/resolve/testData/resolve/expresssions/checkArguments.kt"); } + @TestMetadata("companion.kt") + public void testCompanion() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/expresssions/companion.kt"); + } + @TestMetadata("constructor.kt") public void testConstructor() throws Exception { runTest("compiler/fir/resolve/testData/resolve/expresssions/constructor.kt"); diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirRegularClass.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirRegularClass.kt index 5423d193abc..9328153f704 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirRegularClass.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirRegularClass.kt @@ -24,6 +24,8 @@ interface FirRegularClass : FirClass, @VisitedSupertype FirClassLikeDeclaration, val isInline: Boolean get() = status.isInline + val companionObject: FirRegularClass? + override val symbol: FirClassSymbol override fun accept(visitor: FirVisitor, data: D): R = diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirClassImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirClassImpl.kt index 8870077a414..7ba1e31ae7b 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirClassImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirClassImpl.kt @@ -46,6 +46,19 @@ open class FirClassImpl( override val declarations = mutableListOf() + override var companionObject: FirRegularClass? = null + + fun addDeclaration(declaration: FirDeclaration) { + declarations += declaration + if (companionObject == null && declaration is FirRegularClass && declaration.isCompanion) { + companionObject = declaration + } + } + + fun addDeclarations(declarations: Collection) { + declarations.forEach(this::addDeclaration) + } + override fun replaceSupertypes(newSupertypes: List): FirRegularClass { superTypeRefs.clear() superTypeRefs.addAll(newSupertypes) @@ -58,6 +71,7 @@ open class FirClassImpl( // Transform declarations in last turn declarations.transformInplace(transformer, data) + companionObject = declarations.asSequence().filterIsInstance().firstOrNull { it.isCompanion } return result } }