diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt index 51b89e3fac3..4361a1b54a3 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.load.java.JavaClassFinder import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder @@ -34,6 +35,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.serialization.deserialization.getName +import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult class KotlinDeserializedJvmSymbolsProvider( val session: FirSession, @@ -44,13 +46,18 @@ class KotlinDeserializedJvmSymbolsProvider( ) : AbstractFirSymbolProvider() { private val classesCache = mutableMapOf() + private val typeAliasCache = mutableMapOf() private val packagePartsCache = mutableMapOf>() private class PackagePartsCacheData(val proto: ProtoBuf.Package, val context: FirDeserializationContext) { - val topLevelNameIndex by lazy { + val topLevelFunctionNameIndex by lazy { proto.functionList.withIndex() .groupBy({ context.nameResolver.getName(it.value.name) }) { (index) -> index } } + val typeAliasNameIndex by lazy { + proto.typeAliasList.withIndex() + .groupBy({ context.nameResolver.getName(it.value.name) }) { (index) -> index } + } } private val knownClassNamesInPackage = mutableMapOf?>() @@ -91,9 +98,24 @@ class KotlinDeserializedJvmSymbolsProvider( } override fun getClassLikeSymbolByFqName(classId: ClassId): ConeClassLikeSymbol? { - return findAndDeserializeClass(classId) + return findAndDeserializeClass(classId) ?: findAndDeserializeTypeAlias(classId) } + private fun findAndDeserializeTypeAlias( + classId: ClassId + ): FirTypeAliasSymbol? { + return typeAliasCache.getOrPut(classId) { + getPackageParts(classId.packageFqName).firstNotNullResult { part -> + val ids = part.typeAliasNameIndex[classId.shortClassName] + if (ids == null || ids.isEmpty()) return@firstNotNullResult null + val aliasProto = ids.map { part.proto.getTypeAlias(it) }.single() + + part.context.memberDeserializer.loadTypeAlias(aliasProto).symbol + } + } + } + + private fun findAndDeserializeClass( classId: ClassId, parentContext: FirDeserializationContext? = null @@ -119,7 +141,7 @@ class KotlinDeserializedJvmSymbolsProvider( override fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List { return getPackageParts(packageFqName).flatMap { part -> - val functionIds = part.topLevelNameIndex[name] ?: return@flatMap emptyList() + val functionIds = part.topLevelFunctionNameIndex[name] ?: return@flatMap emptyList() functionIds.map { part.proto.getFunction(it) } .map { part.context.memberDeserializer.loadFunction(it).symbol diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt index d6ad334f492..23afcfaf812 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt @@ -122,6 +122,27 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) { return lowSixBits + rest } + fun loadTypeAlias(proto: ProtoBuf.TypeAlias): FirTypeAlias { + val flags = proto.flags + val name = c.nameResolver.getName(proto.name) + return FirTypeAliasImpl( + c.session, + null, + FirTypeAliasSymbol(ClassId(c.packageFqName, name)), + name, + ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags)), + Flags.IS_EXPECT_CLASS.get(flags), + false, + FirResolvedTypeRefImpl( + c.session, + null, + c.typeDeserializer.type(proto.underlyingType(c.typeTable)), + false, + emptyList() /* TODO */ + ) + ) + } + fun loadFunction(proto: ProtoBuf.Function): FirNamedFunction { val flags = if (proto.hasFlags()) proto.flags else loadOldFlags(proto.oldFlags) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypeResolverTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypeResolverTransformer.kt index a4edc5e945d..d2e250347c2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypeResolverTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypeResolverTransformer.kt @@ -156,10 +156,13 @@ class FirSupertypeResolverTransformer : FirAbstractTreeTransformer() { sessionForSupertype .getService(FirSymbolProvider::class) .getClassLikeSymbolByFqName(superTypeClassId) - ?.toFirClassLike() as? FirClass + ?.toFirClassLike() // TODO: this if is a temporary hack for built-in types (because we can't load file for them) - if (firClassForSupertype == null || firClassForSupertype.superTypeRefs.any { it !is FirResolvedTypeRef }) { + if (firClassForSupertype == null || + (firClassForSupertype is FirClass && + firClassForSupertype.superTypeRefs.any { it !is FirResolvedTypeRef }) + ) { val provider = sessionForSupertype.getService(FirProvider::class) val firForSuperClassFile = provider.getFirClassifierContainerFile(superTypeClassId) diff --git a/compiler/fir/resolve/testData/resolve/stdlib/typeAliasDeserialization.kt b/compiler/fir/resolve/testData/resolve/stdlib/typeAliasDeserialization.kt new file mode 100644 index 00000000000..39b5c6dde81 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/stdlib/typeAliasDeserialization.kt @@ -0,0 +1,4 @@ +fun main() { + val a = LinkedHashSet() + a.add("") +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/stdlib/typeAliasDeserialization.txt b/compiler/fir/resolve/testData/resolve/stdlib/typeAliasDeserialization.txt new file mode 100644 index 00000000000..195fac70c05 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/stdlib/typeAliasDeserialization.txt @@ -0,0 +1,5 @@ +FILE: typeAliasDeserialization.kt + public final fun main(): R|kotlin/Unit| { + lval a: R|java/util/LinkedHashSet| = R|java/util/LinkedHashSet.LinkedHashSet|() + R|/a|.#(String()) + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseWithStdlibGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseWithStdlibGenerated.java index 4be86e47bf4..6ed336808f6 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseWithStdlibGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseWithStdlibGenerated.java @@ -59,6 +59,11 @@ public class FirResolveTestCaseWithStdlibGenerated extends AbstractFirResolveTes runTest("compiler/fir/resolve/testData/resolve/stdlib/reflectionClass.kt"); } + @TestMetadata("typeAliasDeserialization.kt") + public void testTypeAliasDeserialization() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/stdlib/typeAliasDeserialization.kt"); + } + @TestMetadata("unaryOperators.kt") public void testUnaryOperators() throws Exception { runTest("compiler/fir/resolve/testData/resolve/stdlib/unaryOperators.kt");