[Plugin API] Add API to load top level declaration by its signature

- request from JP Compose, #KT-44100
This commit is contained in:
Roman Artemev
2021-02-08 14:43:33 +03:00
parent ca6e1b8f1b
commit d97a2b13c0
4 changed files with 45 additions and 0 deletions
@@ -10,7 +10,9 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.linkage.IrDeserializer
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
@@ -51,4 +53,7 @@ interface IrPluginContext : IrGeneratorContext {
fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol>
fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol>
fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol>
// temporary solution to load synthetic top-level declaration
fun referenceTopLevel(signature: IdSignature, kind: IrDeserializer.TopLevelSymbolKind, moduleDescriptor: ModuleDescriptor): IrSymbol?
}
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.linkage.IrDeserializer
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
@@ -134,4 +135,14 @@ open class IrPluginContextImpl constructor(
descriptors.map { st.referenceProperty(it) }
}
}
override fun referenceTopLevel(
signature: IdSignature,
kind: IrDeserializer.TopLevelSymbolKind,
moduleDescriptor: ModuleDescriptor
): IrSymbol? {
val symbol = linker.resolveBySignatureInModule(signature, kind, moduleDescriptor.name)
linker.postProcess()
return symbol
}
}
@@ -9,6 +9,8 @@ import org.jetbrains.kotlin.ir.builders.TranslationPluginContext
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.name.Name
interface IrDeserializer : IrProvider {
@@ -16,6 +18,14 @@ interface IrDeserializer : IrProvider {
fun resolveSymbol(symbol: IrSymbol, context: TranslationPluginContext): IrDeclaration? = null
}
enum class TopLevelSymbolKind {
FUNCTION_SYMBOL,
CLASS_SYMBOL,
PROPERTY_SYMBOL,
TYPEALIAS_SYMBOL;
}
fun init(moduleFragment: IrModuleFragment?, extensions: Collection<IrLinkerExtension>) {}
fun resolveBySignatureInModule(signature: IdSignature, kind: TopLevelSymbolKind, moduleName: Name): IrSymbol
fun postProcess() {}
}
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.protobuf.CodedInputStream
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite.newInstance
import org.jetbrains.kotlin.resolve.descriptorUtil.module
@@ -64,6 +65,7 @@ abstract class KotlinIrLinker(
private val modulesWithReachableTopLevels = mutableSetOf<IrModuleDeserializer>()
// TODO: replace with Map<Name, IrModuleDeserializer>
protected val deserializersForModules = mutableMapOf<ModuleDescriptor, IrModuleDeserializer>()
abstract val fakeOverrideBuilder: FakeOverrideBuilder
@@ -665,6 +667,23 @@ abstract class KotlinIrLinker(
// symbolTable.noUnboundLeft("unbound after fake overrides:")
}
private fun topLevelKindToSymbolKind(kind: IrDeserializer.TopLevelSymbolKind): BinarySymbolData.SymbolKind {
return when (kind) {
IrDeserializer.TopLevelSymbolKind.CLASS_SYMBOL -> BinarySymbolData.SymbolKind.CLASS_SYMBOL
IrDeserializer.TopLevelSymbolKind.PROPERTY_SYMBOL -> BinarySymbolData.SymbolKind.PROPERTY_SYMBOL
IrDeserializer.TopLevelSymbolKind.FUNCTION_SYMBOL -> BinarySymbolData.SymbolKind.FUNCTION_SYMBOL
IrDeserializer.TopLevelSymbolKind.TYPEALIAS_SYMBOL -> BinarySymbolData.SymbolKind.TYPEALIAS_SYMBOL
}
}
override fun resolveBySignatureInModule(signature: IdSignature, kind: IrDeserializer.TopLevelSymbolKind, moduleName: Name): IrSymbol {
val moduleDeserializer =
deserializersForModules.entries.find { it.key.name == moduleName }?.value ?: error("No module for name '$moduleName' found")
assert(signature == signature.topLevelSignature()) { "Signature '$signature' has to be top level" }
if (signature !in moduleDeserializer) error("No signature $signature in module $moduleName")
return moduleDeserializer.deserializeIrSymbol(signature, topLevelKindToSymbolKind(kind))
}
// The issue here is that an expect can not trigger its actual deserialization by reachability
// because the expect can not see the actual higher in the module dependency dag.
// So we force deserialization of actuals for all deserialized expect symbols here.