FIR deserializer: support type-aliases
This commit is contained in:
committed by
Mikhail Glukhikh
parent
e6ab38a583
commit
8324ee7272
+25
-3
@@ -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<ClassId, FirClassSymbol>()
|
||||
private val typeAliasCache = mutableMapOf<ClassId, FirTypeAliasSymbol?>()
|
||||
private val packagePartsCache = mutableMapOf<FqName, Collection<PackagePartsCacheData>>()
|
||||
|
||||
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<FqName, Set<String>?>()
|
||||
@@ -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<ConeCallableSymbol> {
|
||||
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
|
||||
|
||||
+21
@@ -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)
|
||||
|
||||
|
||||
+5
-2
@@ -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)
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
fun main() {
|
||||
val a = LinkedHashSet<String>()
|
||||
a.add("")
|
||||
}
|
||||
@@ -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|<local>/a|.<Inapplicable(INAPPLICABLE): [java/util/HashSet.add, java/util/AbstractCollection.add, java/util/Collection.add, java/util/Set.add]>#(String())
|
||||
}
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user