[FIR] Add MetadataSymbolProvider
Extract common code from K1 to MetadataUtil
This commit is contained in:
committed by
Space Team
parent
c103da98dd
commit
e22359cc10
+3
@@ -37,6 +37,9 @@ class DirectoryBasedClassFinder(
|
|||||||
// TODO
|
// TODO
|
||||||
override fun findMetadata(classId: ClassId): InputStream? = null
|
override fun findMetadata(classId: ClassId): InputStream? = null
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
override fun findMetadataTopLevelClassesInPackage(packageFqName: FqName): Set<String>? = null
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
override fun hasMetadataPackage(fqName: FqName): Boolean = false
|
override fun hasMetadataPackage(fqName: FqName): Boolean = false
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.cli.jvm.compiler
|
|||||||
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
|
import gnu.trove.THashSet
|
||||||
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
|
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
|
||||||
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
|
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
|
||||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
|
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
|
||||||
@@ -49,6 +50,21 @@ class CliVirtualFileFinder(
|
|||||||
)?.inputStream
|
)?.inputStream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun findMetadataTopLevelClassesInPackage(packageFqName: FqName): Set<String> {
|
||||||
|
val result = THashSet<String>()
|
||||||
|
index.traverseDirectoriesInPackage(packageFqName, continueSearch = { dir, _ ->
|
||||||
|
for (child in dir.children) {
|
||||||
|
if (child.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION) {
|
||||||
|
result.add(child.nameWithoutExtension)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
override fun hasMetadataPackage(fqName: FqName): Boolean {
|
override fun hasMetadataPackage(fqName: FqName): Boolean {
|
||||||
var found = false
|
var found = false
|
||||||
index.traverseDirectoriesInPackage(fqName, continueSearch = { dir, _ ->
|
index.traverseDirectoriesInPackage(fqName, continueSearch = { dir, _ ->
|
||||||
|
|||||||
+1
-7
@@ -34,12 +34,6 @@ import org.jetbrains.kotlin.utils.toMetadataVersion
|
|||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
|
|
||||||
/**
|
|
||||||
* Any top level declarations in core/builtins/src are also available from FirBuiltinSymbolProvider (or FirIdeBuiltinSymbolProvider) for IDE
|
|
||||||
* so we filter them out to avoid providing the "same" symbols twice.
|
|
||||||
*/
|
|
||||||
private val kotlinBuiltins = setOf("kotlin/ArrayIntrinsicsKt", "kotlin/internal/ProgressionUtilKt")
|
|
||||||
|
|
||||||
// This symbol provider loads JVM classes, reading extra info from Kotlin `@Metadata` annotations
|
// This symbol provider loads JVM classes, reading extra info from Kotlin `@Metadata` annotations
|
||||||
// if present. Use it for library and incremental compilation sessions. For source sessions use
|
// if present. Use it for library and incremental compilation sessions. For source sessions use
|
||||||
// `JavaSymbolProvider`, as Kotlin classes should be parsed first.
|
// `JavaSymbolProvider`, as Kotlin classes should be parsed first.
|
||||||
@@ -59,7 +53,7 @@ class JvmClassFileBasedSymbolProvider(
|
|||||||
|
|
||||||
override fun computePackagePartsInfos(packageFqName: FqName): List<PackagePartsCacheData> {
|
override fun computePackagePartsInfos(packageFqName: FqName): List<PackagePartsCacheData> {
|
||||||
return packagePartProvider.findPackageParts(packageFqName.asString()).mapNotNull { partName ->
|
return packagePartProvider.findPackageParts(packageFqName.asString()).mapNotNull { partName ->
|
||||||
if (partName in kotlinBuiltins) return@mapNotNull null
|
if (partName in KotlinBuiltins) return@mapNotNull null
|
||||||
val classId = ClassId.topLevel(JvmClassName.byInternalName(partName).fqNameForTopLevelClassMaybeWithDollars)
|
val classId = ClassId.topLevel(JvmClassName.byInternalName(partName).fqNameForTopLevelClassMaybeWithDollars)
|
||||||
if (!javaFacade.hasTopLevelClassOf(classId)) return@mapNotNull null
|
if (!javaFacade.hasTopLevelClassOf(classId)) return@mapNotNull null
|
||||||
val jvmMetadataVersion = session.languageVersionSettings.languageVersion.toMetadataVersion()
|
val jvmMetadataVersion = session.languageVersionSettings.languageVersion.toMetadataVersion()
|
||||||
|
|||||||
+84
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.java.deserialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.ThreadSafeMutableState
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.fir.deserialization.*
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
||||||
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.KotlinMetadataFinder
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.MetadataClassDataFinder
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.MetadataPartProvider
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.readProto
|
||||||
|
|
||||||
|
@ThreadSafeMutableState
|
||||||
|
class MetadataSymbolProvider(
|
||||||
|
session: FirSession,
|
||||||
|
moduleDataProvider: ModuleDataProvider,
|
||||||
|
kotlinScopeProvider: FirKotlinScopeProvider,
|
||||||
|
private val packagePartProvider: PackagePartProvider,
|
||||||
|
private val kotlinClassFinder: KotlinMetadataFinder,
|
||||||
|
defaultDeserializationOrigin: FirDeclarationOrigin = FirDeclarationOrigin.Library
|
||||||
|
) : AbstractFirDeserializedSymbolProvider(
|
||||||
|
session, moduleDataProvider, kotlinScopeProvider, defaultDeserializationOrigin, BuiltInSerializerProtocol
|
||||||
|
) {
|
||||||
|
private val metadataPartProvider = packagePartProvider as MetadataPartProvider
|
||||||
|
|
||||||
|
private val classDataFinder = MetadataClassDataFinder(kotlinClassFinder)
|
||||||
|
|
||||||
|
private val annotationDeserializer = FirBuiltinAnnotationDeserializer(session)
|
||||||
|
|
||||||
|
private val constDeserializer = FirConstDeserializer(session, BuiltInSerializerProtocol)
|
||||||
|
|
||||||
|
override fun computePackagePartsInfos(packageFqName: FqName): List<PackagePartsCacheData> {
|
||||||
|
return metadataPartProvider.findMetadataPackageParts(packageFqName.asString()).mapNotNull { partName ->
|
||||||
|
if (partName in KotlinBuiltins) return@mapNotNull null
|
||||||
|
val classId = ClassId(packageFqName, Name.identifier(partName))
|
||||||
|
|
||||||
|
val stream = kotlinClassFinder.findMetadata(classId) ?: return@mapNotNull null
|
||||||
|
val (proto, nameResolver, _) = readProto(stream)
|
||||||
|
|
||||||
|
val context = FirDeserializationContext.createForPackage(
|
||||||
|
packageFqName,
|
||||||
|
proto.`package`,
|
||||||
|
nameResolver,
|
||||||
|
moduleDataProvider.allModuleData.last(),
|
||||||
|
annotationDeserializer = annotationDeserializer,
|
||||||
|
constDeserializer = constDeserializer,
|
||||||
|
containerSource = null
|
||||||
|
)
|
||||||
|
|
||||||
|
return@mapNotNull PackagePartsCacheData(proto.`package`, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun computePackageSetWithNonClassDeclarations() = packagePartProvider.computePackageSetWithNonClassDeclarations()
|
||||||
|
|
||||||
|
override fun knownTopLevelClassesInPackage(packageFqName: FqName) = kotlinClassFinder.findMetadataTopLevelClassesInPackage(packageFqName)
|
||||||
|
|
||||||
|
override fun extractClassMetadata(classId: ClassId, parentContext: FirDeserializationContext?): ClassMetadataFindResult? {
|
||||||
|
val classData = classDataFinder.findClassData(classId) ?: return null
|
||||||
|
return ClassMetadataFindResult.Metadata(
|
||||||
|
classData.nameResolver,
|
||||||
|
classData.classProto,
|
||||||
|
annotationDeserializer = null,
|
||||||
|
moduleDataProvider.allModuleData.last(),
|
||||||
|
sourceElement = null,
|
||||||
|
classPostProcessor = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isNewPlaceForBodyGeneration(classProto: ProtoBuf.Class) = false
|
||||||
|
|
||||||
|
override fun getPackage(fqName: FqName) = null
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.java.deserialization
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any top level declarations in core/builtins/src are also available from FirBuiltinSymbolProvider (or FirIdeBuiltinSymbolProvider) for IDE
|
||||||
|
* so we filter them out to avoid providing the "same" symbols twice.
|
||||||
|
*/
|
||||||
|
val KotlinBuiltins = setOf("kotlin/ArrayIntrinsicsKt", "kotlin/internal/ProgressionUtilKt")
|
||||||
+2
@@ -27,6 +27,8 @@ interface KotlinMetadataFinder {
|
|||||||
*/
|
*/
|
||||||
fun findMetadata(classId: ClassId): InputStream?
|
fun findMetadata(classId: ClassId): InputStream?
|
||||||
|
|
||||||
|
fun findMetadataTopLevelClassesInPackage(packageFqName: FqName): Set<String>?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return `true` iff this finder is able to locate the package with the given [fqName], containing .kotlin_metadata files.
|
* @return `true` iff this finder is able to locate the package with the given [fqName], containing .kotlin_metadata files.
|
||||||
* Note that returning `true` makes [MetadataPackageFragmentProvider] construct the package fragment for the package,
|
* Note that returning `true` makes [MetadataPackageFragmentProvider] construct the package fragment for the package,
|
||||||
|
|||||||
+3
@@ -45,6 +45,9 @@ class ReflectKotlinClassFinder(private val classLoader: ClassLoader) : KotlinCla
|
|||||||
// TODO
|
// TODO
|
||||||
override fun findMetadata(classId: ClassId): InputStream? = null
|
override fun findMetadata(classId: ClassId): InputStream? = null
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
override fun findMetadataTopLevelClassesInPackage(packageFqName: FqName): Set<String>? = null
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
override fun hasMetadataPackage(fqName: FqName): Boolean = false
|
override fun hasMetadataPackage(fqName: FqName): Boolean = false
|
||||||
|
|
||||||
|
|||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.serialization.deserialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||||
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
|
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
|
||||||
|
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
class MetadataClassDataFinder(val finder: KotlinMetadataFinder) : ClassDataFinder {
|
||||||
|
override fun findClassData(classId: ClassId): ClassData? {
|
||||||
|
val topLevelClassId = generateSequence(classId, ClassId::getOuterClassId).last()
|
||||||
|
val stream = finder.findMetadata(topLevelClassId) ?: return null
|
||||||
|
val (message, nameResolver, version) = readProto(stream)
|
||||||
|
return message.class_List.firstOrNull { classProto ->
|
||||||
|
nameResolver.getClassId(classProto.fqName) == classId
|
||||||
|
}?.let { classProto ->
|
||||||
|
ClassData(nameResolver, classProto, version, SourceElement.NO_SOURCE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun readProto(stream: InputStream): Triple<ProtoBuf.PackageFragment, NameResolverImpl, BuiltInsBinaryVersion> {
|
||||||
|
val version = BuiltInsBinaryVersion.readFrom(stream)
|
||||||
|
|
||||||
|
if (!version.isCompatibleWithCurrentCompilerVersion()) {
|
||||||
|
// TODO: report a proper diagnostic
|
||||||
|
throw UnsupportedOperationException(
|
||||||
|
"Kotlin metadata definition format version is not supported: " +
|
||||||
|
"expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " +
|
||||||
|
"Please update Kotlin"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val message = ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
|
||||||
|
val nameResolver = NameResolverImpl(message.strings, message.qualifiedNames)
|
||||||
|
return Triple(message, nameResolver, version)
|
||||||
|
}
|
||||||
+1
-29
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.serialization.deserialization
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.NotFoundClasses
|
import org.jetbrains.kotlin.descriptors.NotFoundClasses
|
||||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
|
||||||
import org.jetbrains.kotlin.descriptors.deserialization.AdditionalClassPartsProvider
|
import org.jetbrains.kotlin.descriptors.deserialization.AdditionalClassPartsProvider
|
||||||
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentDeclarationFilter
|
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentDeclarationFilter
|
||||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
@@ -36,7 +35,6 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
|||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.extensions.TypeAttributeTranslators
|
import org.jetbrains.kotlin.types.extensions.TypeAttributeTranslators
|
||||||
import java.io.InputStream
|
|
||||||
|
|
||||||
class MetadataPackageFragmentProvider(
|
class MetadataPackageFragmentProvider(
|
||||||
storageManager: StorageManager,
|
storageManager: StorageManager,
|
||||||
@@ -85,16 +83,7 @@ class MetadataPackageFragment(
|
|||||||
private val metadataPartProvider: MetadataPartProvider,
|
private val metadataPartProvider: MetadataPartProvider,
|
||||||
private val finder: KotlinMetadataFinder
|
private val finder: KotlinMetadataFinder
|
||||||
) : DeserializedPackageFragment(fqName, storageManager, module) {
|
) : DeserializedPackageFragment(fqName, storageManager, module) {
|
||||||
override val classDataFinder = ClassDataFinder { classId ->
|
override val classDataFinder = MetadataClassDataFinder(finder)
|
||||||
val topLevelClassId = generateSequence(classId, ClassId::getOuterClassId).last()
|
|
||||||
val stream = finder.findMetadata(topLevelClassId) ?: return@ClassDataFinder null
|
|
||||||
val (message, nameResolver, version) = readProto(stream)
|
|
||||||
message.class_List.firstOrNull { classProto ->
|
|
||||||
nameResolver.getClassId(classProto.fqName) == classId
|
|
||||||
}?.let { classProto ->
|
|
||||||
ClassData(nameResolver, classProto, version, SourceElement.NO_SOURCE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var components: DeserializationComponents
|
private lateinit var components: DeserializationComponents
|
||||||
|
|
||||||
@@ -152,23 +141,6 @@ class MetadataPackageFragment(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readProto(stream: InputStream): Triple<ProtoBuf.PackageFragment, NameResolverImpl, BuiltInsBinaryVersion> {
|
|
||||||
val version = BuiltInsBinaryVersion.readFrom(stream)
|
|
||||||
|
|
||||||
if (!version.isCompatibleWithCurrentCompilerVersion()) {
|
|
||||||
// TODO: report a proper diagnostic
|
|
||||||
throw UnsupportedOperationException(
|
|
||||||
"Kotlin metadata definition format version is not supported: " +
|
|
||||||
"expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " +
|
|
||||||
"Please update Kotlin"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val message = ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
|
|
||||||
val nameResolver = NameResolverImpl(message.strings, message.qualifiedNames)
|
|
||||||
return Triple(message, nameResolver, version)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val METADATA_FILE_EXTENSION = "kotlin_metadata"
|
const val METADATA_FILE_EXTENSION = "kotlin_metadata"
|
||||||
const val DOT_METADATA_FILE_EXTENSION = ".$METADATA_FILE_EXTENSION"
|
const val DOT_METADATA_FILE_EXTENSION = ".$METADATA_FILE_EXTENSION"
|
||||||
|
|||||||
Reference in New Issue
Block a user