Rework DescriptorSerializerPlugin to be a part of Project's extensions

instead of statically registering it.

Static registering can cause subtle errors when plugin implementation
(e.g. SerializationDescriptorPluginForKotlinxSerialization) is registered
from multiple classloaders: in multi-module with daemon compilation scenario

 #KT-41857 Fixed
This commit is contained in:
Leonid Startsev
2020-10-15 17:01:37 +03:00
parent ef907e0c46
commit 4ec90b18bc
23 changed files with 115 additions and 67 deletions
@@ -69,5 +69,7 @@
dynamic="true"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar"
interface="org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.DescriptorSerializerPlugin"
interface="org.jetbrains.kotlin.serialization.DescriptorSerializerPlugin"/>
</extensionPoints>
</idea-plugin>
@@ -99,6 +99,7 @@ import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtens
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import org.jetbrains.kotlin.resolve.lazy.declarations.CliDeclarationProviderFactoryService
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
import org.jetbrains.kotlin.serialization.DescriptorSerializerPlugin
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
import java.util.zip.ZipFile
@@ -555,6 +556,7 @@ class KotlinCoreEnvironment private constructor(
ShellExtension.registerExtensionPoint(project)
TypeResolutionInterceptor.registerExtensionPoint(project)
CandidateInterceptor.registerExtensionPoint(project)
DescriptorSerializerPlugin.registerExtensionPoint(project)
}
internal fun registerExtensionsFromPlugins(project: MockProject, configuration: CompilerConfiguration) {
@@ -103,6 +103,7 @@ import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtens
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import org.jetbrains.kotlin.resolve.lazy.declarations.CliDeclarationProviderFactoryService
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
import org.jetbrains.kotlin.serialization.DescriptorSerializerPlugin
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
import java.util.zip.ZipFile
@@ -556,6 +557,7 @@ class KotlinCoreEnvironment private constructor(
ShellExtension.registerExtensionPoint(project)
TypeResolutionInterceptor.registerExtensionPoint(project)
CandidateInterceptor.registerExtensionPoint(project)
DescriptorSerializerPlugin.registerExtensionPoint(project)
}
internal fun registerExtensionsFromPlugins(project: MockProject, configuration: CompilerConfiguration) {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.cli.metadata
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
@@ -60,17 +61,19 @@ internal class K2MetadataKlibSerializer(private val metadataVersion: BuiltInsBin
val (_, moduleDescriptor) = analyzer.analysisResult
val destDir = checkNotNull(environment.destDir)
performSerialization(configuration, moduleDescriptor, destDir)
performSerialization(configuration, moduleDescriptor, destDir, environment.project)
}
private fun performSerialization(
configuration: CompilerConfiguration,
module: ModuleDescriptor,
destDir: File
destDir: File,
project: Project
) {
val serializedMetadata: SerializedMetadata = KlibMetadataMonolithicSerializer(
configuration.languageVersionSettings,
metadataVersion,
project,
skipExpects = false,
includeOnlyModuleContent = true
).serializeModule(module)
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.cli.metadata
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.descriptors.ClassDescriptor
@@ -45,11 +46,11 @@ open class MetadataSerializer(
val (bindingContext, moduleDescriptor) = analyzer.analysisResult
val destDir = checkNotNull(environment.destDir)
performSerialization(environment.getSourceFiles(), bindingContext, moduleDescriptor, destDir)
performSerialization(environment.getSourceFiles(), bindingContext, moduleDescriptor, destDir, environment.project)
}
protected open fun performSerialization(
files: Collection<KtFile>, bindingContext: BindingContext, module: ModuleDescriptor, destDir: File
files: Collection<KtFile>, bindingContext: BindingContext, module: ModuleDescriptor, destDir: File, project: Project?
) {
val packageTable = hashMapOf<FqName, PackageParts>()
@@ -83,14 +84,14 @@ open class MetadataSerializer(
val classDescriptor = bindingContext.get(BindingContext.CLASS, classOrObject)
?: error("No descriptor found for class ${classOrObject.fqName}")
val destFile = File(destDir, getClassFilePath(ClassId(packageFqName, classDescriptor.name)))
PackageSerializer(listOf(classDescriptor), emptyList(), packageFqName, destFile).run()
PackageSerializer(listOf(classDescriptor), emptyList(), packageFqName, destFile, project).run()
}
})
}
if (members.isNotEmpty()) {
val destFile = File(destDir, getPackageFilePath(packageFqName, file.name))
PackageSerializer(emptyList(), members, packageFqName, destFile).run()
PackageSerializer(emptyList(), members, packageFqName, destFile, project).run()
packageTable.getOrPut(packageFqName) {
PackageParts(packageFqName.asString())
@@ -123,27 +124,29 @@ open class MetadataSerializer(
private val classes: Collection<DeclarationDescriptor>,
private val members: Collection<DeclarationDescriptor>,
private val packageFqName: FqName,
private val destFile: File
private val destFile: File,
private val project: Project? = null
) {
private val proto = ProtoBuf.PackageFragment.newBuilder()
private val extension = createSerializerExtension()
fun run() {
val serializer = DescriptorSerializer.createTopLevel(extension)
serializeClasses(classes, serializer)
serializeClasses(classes, serializer, project)
serializeMembers(members, serializer)
serializeStringTable()
serializeBuiltInsFile()
}
private fun serializeClasses(classes: Collection<DeclarationDescriptor>, parentSerializer: DescriptorSerializer) {
private fun serializeClasses(classes: Collection<DeclarationDescriptor>, parentSerializer: DescriptorSerializer, project: Project?) {
for (descriptor in DescriptorSerializer.sort(classes)) {
if (descriptor !is ClassDescriptor || descriptor.kind == ClassKind.ENUM_ENTRY) continue
val serializer = DescriptorSerializer.create(descriptor, extension, parentSerializer)
val serializer = DescriptorSerializer.create(descriptor, extension, parentSerializer, project)
serializeClasses(
descriptor.unsubstitutedInnerClassesScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS),
serializer
serializer,
project
)
proto.addClass_(serializer.classProto(descriptor).build())