K2 Scripting: implement basic metadata serialization support
#KT-62305 fixed NB: kotlin reflection do not see script class constructor after this change, and it's ok, since the fact that the script is compiled into a class is an implementation detail. If needed, java reflection could be used to access the constructor.
This commit is contained in:
committed by
Space Team
parent
122f16fc18
commit
31f9e9e7a8
+102
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.scopes.*
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirScriptDeclarationsScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope
|
||||
import org.jetbrains.kotlin.fir.serialization.constant.hasConstantValue
|
||||
import org.jetbrains.kotlin.fir.serialization.constant.toConstantValue
|
||||
@@ -293,6 +294,88 @@ class FirElementSerializer private constructor(
|
||||
return builder
|
||||
}
|
||||
|
||||
fun scriptProto(script: FirScript): ProtoBuf.Class.Builder = whileAnalysing(session, script) {
|
||||
val builder = ProtoBuf.Class.newBuilder()
|
||||
|
||||
val flags = Flags.getClassFlags(
|
||||
extension.hasAdditionalAnnotations(script),
|
||||
ProtoEnumFlags.visibility(Visibilities.Public),
|
||||
ProtoEnumFlags.modality(Modality.FINAL),
|
||||
ProtoEnumFlags.classKind(ClassKind.CLASS, false),
|
||||
/* inner = */ false,
|
||||
/* isData = */ false,
|
||||
/* isExternal = */ false,
|
||||
/* isExpect = */ false,
|
||||
/* isValue = */ false,
|
||||
/* isFun = */ false,
|
||||
/* hasEnumEntries = */ false,
|
||||
)
|
||||
if (flags != builder.flags) {
|
||||
builder.flags = flags
|
||||
}
|
||||
|
||||
val name = script.name.let {
|
||||
if (it.isSpecial) {
|
||||
NameUtils.getScriptNameForFile(it.asStringStripSpecialMarkers().removePrefix("script-"))
|
||||
} else it
|
||||
}
|
||||
val classId = ClassId(script.symbol.fqName.parentOrNull() ?: FqName.ROOT, name)
|
||||
|
||||
builder.fqName = getClassifierId(classId)
|
||||
|
||||
val memberScope = FirScriptDeclarationsScope(session, script)
|
||||
|
||||
val callableMembers = buildList {
|
||||
memberScope.processAllCallables { add(it.fir) }
|
||||
}
|
||||
|
||||
for (declaration in callableMembers) {
|
||||
when (declaration) {
|
||||
is FirProperty -> propertyProto(declaration)?.let { builder.addProperty(it) }
|
||||
is FirSimpleFunction -> functionProto(declaration)?.let { builder.addFunction(it) }
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
memberScope.getClassifierNames().forEach { classifierName ->
|
||||
memberScope.processClassifiersByName(classifierName) { nestedClassifier ->
|
||||
when (nestedClassifier) {
|
||||
is FirRegularClassSymbol -> {
|
||||
builder.addNestedClassName(getSimpleNameIndex(nestedClassifier.name))
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (contextReceiver in script.contextReceivers) {
|
||||
val typeRef = contextReceiver.typeRef
|
||||
if (useTypeTable()) {
|
||||
builder.addContextReceiverTypeId(typeId(typeRef))
|
||||
} else {
|
||||
builder.addContextReceiverType(typeProto(contextReceiver.typeRef))
|
||||
}
|
||||
}
|
||||
|
||||
if (versionRequirementTable == null) error("Version requirements must be serialized for scripts: ${script.render()}")
|
||||
|
||||
builder.addAllVersionRequirement(versionRequirementTable.serializeVersionRequirements(script))
|
||||
|
||||
extension.serializeScript(script, builder, versionRequirementTable, this)
|
||||
|
||||
if (metDefinitelyNotNullType) {
|
||||
builder.addVersionRequirement(
|
||||
writeLanguageVersionRequirement(LanguageFeature.DefinitelyNonNullableTypes, versionRequirementTable)
|
||||
)
|
||||
}
|
||||
|
||||
typeTable.serialize()?.let { builder.typeTable = it }
|
||||
versionRequirementTable.serialize()?.let { builder.versionRequirementTable = it }
|
||||
|
||||
return builder
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Order of nested classifiers:
|
||||
* - declared classifiers in declaration order
|
||||
@@ -1237,6 +1320,25 @@ class FirElementSerializer private constructor(
|
||||
return serializer
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun createForScript(
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
script: FirScript,
|
||||
extension: FirSerializerExtension,
|
||||
typeApproximator: AbstractTypeApproximator,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
produceHeaderKlib: Boolean = false,
|
||||
): FirElementSerializer =
|
||||
FirElementSerializer(
|
||||
session, scopeSession, script,
|
||||
Interner(), extension, MutableTypeTable(), MutableVersionRequirementTable(),
|
||||
serializeTypeTableToFunction = false,
|
||||
typeApproximator,
|
||||
languageVersionSettings,
|
||||
produceHeaderKlib,
|
||||
)
|
||||
|
||||
private fun writeLanguageVersionRequirement(
|
||||
languageFeature: LanguageFeature,
|
||||
versionRequirementTable: MutableVersionRequirementTable
|
||||
|
||||
+8
@@ -54,6 +54,14 @@ abstract class FirSerializerExtension {
|
||||
) {
|
||||
}
|
||||
|
||||
open fun serializeScript(
|
||||
script: FirScript,
|
||||
proto: ProtoBuf.Class.Builder,
|
||||
versionRequirementTable: MutableVersionRequirementTable,
|
||||
childSerializer: FirElementSerializer
|
||||
) {
|
||||
}
|
||||
|
||||
open fun serializeConstructor(
|
||||
constructor: FirConstructor,
|
||||
proto: ProtoBuf.Constructor.Builder,
|
||||
|
||||
+8
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.serialization.constant.toConstantValue
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf.Class.Builder
|
||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||
import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -37,6 +38,13 @@ abstract class FirSerializerExtensionBase(
|
||||
klass.serializeAnnotations(proto, protocol.classAnnotation)
|
||||
}
|
||||
|
||||
override fun serializeScript(
|
||||
script: FirScript,
|
||||
proto: Builder,
|
||||
versionRequirementTable: MutableVersionRequirementTable,
|
||||
childSerializer: FirElementSerializer,
|
||||
) {}
|
||||
|
||||
override fun serializeConstructor(
|
||||
constructor: FirConstructor,
|
||||
proto: ProtoBuf.Constructor.Builder,
|
||||
|
||||
Reference in New Issue
Block a user