Extensible mechanism for plugin metadata during descriptor serialization
A mechanism that allows kotlinx.serialization plugin to preserve the correct (program) order of properties after serializing/deserializing descriptors to kotlin metadata, which is needed for correct and stable json serialization of class hierarchies in incremental/multi-module scenario. It uses protobuf extensions.
This commit is contained in:
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2017 JetBrains s.r.o.
|
* Copyright 2010-2020 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.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.incremental
|
package org.jetbrains.kotlin.incremental
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2020 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.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2020 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.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
* Copyright 2010-2020 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.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|||||||
+6
-17
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2016 JetBrains s.r.o.
|
* Copyright 2010-2020 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.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.serialization.builtins
|
package org.jetbrains.kotlin.serialization.builtins
|
||||||
@@ -97,10 +86,10 @@ class BuiltInsSerializer(dependOnOldBuiltIns: Boolean) : MetadataSerializer(Buil
|
|||||||
fqName ->
|
fqName ->
|
||||||
val packageView = module.getPackage(fqName)
|
val packageView = module.getPackage(fqName)
|
||||||
PackageSerializer(
|
PackageSerializer(
|
||||||
packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) + createCloneable(module),
|
packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) + createCloneable(module),
|
||||||
packageView.fragments.flatMap { fragment -> DescriptorUtils.getAllDescriptors(fragment.getMemberScope()) },
|
packageView.fragments.flatMap { fragment -> DescriptorUtils.getAllDescriptors(fragment.getMemberScope()) },
|
||||||
packageView.fqName,
|
packageView.fqName,
|
||||||
File(destDir, BuiltInSerializerProtocol.getBuiltInsFilePath(packageView.fqName))
|
File(destDir, BuiltInSerializerProtocol.getBuiltInsFilePath(packageView.fqName))
|
||||||
).run()
|
).run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2020 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.
|
* 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.cli.metadata
|
package org.jetbrains.kotlin.cli.metadata
|
||||||
|
|
||||||
import org.jetbrains.kotlin.analyzer.*
|
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||||
import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer
|
import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer
|
||||||
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
|
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer
|
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer
|
||||||
|
|||||||
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2017 JetBrains s.r.o.
|
* Copyright 2010-2020 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.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.cli.metadata
|
package org.jetbrains.kotlin.cli.metadata
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2020 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.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2020 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.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
+5
@@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.backend.common.serialization.metadata
|
package org.jetbrains.kotlin.backend.common.serialization.metadata
|
||||||
|
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
|
|||||||
+5
-3
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2020 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.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -98,9 +98,11 @@ abstract class KlibMetadataSerializer(
|
|||||||
val index = classSerializer.stringTable.getFqNameIndex(classDescriptor)
|
val index = classSerializer.stringTable.getFqNameIndex(classDescriptor)
|
||||||
//builder.addExtension(KlibMetadataProtoBuf.className, index)
|
//builder.addExtension(KlibMetadataProtoBuf.className, index)
|
||||||
|
|
||||||
val classes = serializeClasses(packageName/*, builder*/,
|
val classes = serializeClasses(
|
||||||
|
packageName/*, builder*/,
|
||||||
classDescriptor.unsubstitutedInnerClassesScope
|
classDescriptor.unsubstitutedInnerClassesScope
|
||||||
.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS))
|
.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS)
|
||||||
|
)
|
||||||
|
|
||||||
classSerializer = previousSerializer
|
classSerializer = previousSerializer
|
||||||
return classes + Pair(classProto, index)
|
return classes + Pair(classProto, index)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2020 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.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
+14
-3
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2020 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.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -45,7 +45,8 @@ class DescriptorSerializer private constructor(
|
|||||||
private val extension: SerializerExtension,
|
private val extension: SerializerExtension,
|
||||||
val typeTable: MutableTypeTable,
|
val typeTable: MutableTypeTable,
|
||||||
private val versionRequirementTable: MutableVersionRequirementTable?,
|
private val versionRequirementTable: MutableVersionRequirementTable?,
|
||||||
private val serializeTypeTableToFunction: Boolean
|
private val serializeTypeTableToFunction: Boolean,
|
||||||
|
val plugins: List<DescriptorSerializerPlugin> = emptyList()
|
||||||
) {
|
) {
|
||||||
private val contractSerializer = ContractSerializer()
|
private val contractSerializer = ContractSerializer()
|
||||||
|
|
||||||
@@ -152,6 +153,8 @@ class DescriptorSerializer private constructor(
|
|||||||
|
|
||||||
extension.serializeClass(classDescriptor, builder, versionRequirementTable, this)
|
extension.serializeClass(classDescriptor, builder, versionRequirementTable, this)
|
||||||
|
|
||||||
|
plugins.forEach { it.afterClass(classDescriptor, builder, versionRequirementTable, this, extension) }
|
||||||
|
|
||||||
writeVersionRequirementForInlineClasses(classDescriptor, builder, versionRequirementTable)
|
writeVersionRequirementForInlineClasses(classDescriptor, builder, versionRequirementTable)
|
||||||
|
|
||||||
val versionRequirementTableProto = versionRequirementTable.serialize()
|
val versionRequirementTableProto = versionRequirementTable.serialize()
|
||||||
@@ -741,6 +744,13 @@ class DescriptorSerializer private constructor(
|
|||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private val plugins: MutableSet<DescriptorSerializerPlugin> = mutableSetOf()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun registerSerializerPlugin(plugin: DescriptorSerializerPlugin) {
|
||||||
|
plugins.add(plugin)
|
||||||
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun createTopLevel(extension: SerializerExtension): DescriptorSerializer =
|
fun createTopLevel(extension: SerializerExtension): DescriptorSerializer =
|
||||||
DescriptorSerializer(
|
DescriptorSerializer(
|
||||||
@@ -775,7 +785,8 @@ class DescriptorSerializer private constructor(
|
|||||||
MutableTypeTable(),
|
MutableTypeTable(),
|
||||||
if (container is ClassDescriptor && !isVersionRequirementTableWrittenCorrectly(extension.metadataVersion))
|
if (container is ClassDescriptor && !isVersionRequirementTableWrittenCorrectly(extension.metadataVersion))
|
||||||
parent.versionRequirementTable else MutableVersionRequirementTable(),
|
parent.versionRequirementTable else MutableVersionRequirementTable(),
|
||||||
serializeTypeTableToFunction = false
|
serializeTypeTableToFunction = false,
|
||||||
|
plugins.toList()
|
||||||
)
|
)
|
||||||
for (typeParameter in descriptor.declaredTypeParameters) {
|
for (typeParameter in descriptor.declaredTypeParameters) {
|
||||||
serializer.typeParameters.intern(typeParameter)
|
serializer.typeParameters.intern(typeParameter)
|
||||||
|
|||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
|
import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable
|
||||||
|
|
||||||
|
interface DescriptorSerializerPlugin {
|
||||||
|
fun afterClass(
|
||||||
|
descriptor: ClassDescriptor,
|
||||||
|
proto: ProtoBuf.Class.Builder,
|
||||||
|
versionRequirementTable: MutableVersionRequirementTable,
|
||||||
|
childSerializer: DescriptorSerializer,
|
||||||
|
extension: SerializerExtension
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
* Copyright 2010-2020 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.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.generators.protobuf
|
package org.jetbrains.kotlin.generators.protobuf
|
||||||
@@ -59,7 +48,8 @@ val PROTO_PATHS: List<ProtoPath> = listOf(
|
|||||||
ProtoPath("core/metadata.jvm/src/jvm_module.proto"),
|
ProtoPath("core/metadata.jvm/src/jvm_module.proto"),
|
||||||
ProtoPath("build-common/src/java_descriptors.proto"),
|
ProtoPath("build-common/src/java_descriptors.proto"),
|
||||||
ProtoPath("compiler/util-klib-metadata/src/KlibMetadataProtoBuf.proto"),
|
ProtoPath("compiler/util-klib-metadata/src/KlibMetadataProtoBuf.proto"),
|
||||||
ProtoPath("compiler/ir/serialization.common/src/KotlinIr.proto", false)
|
ProtoPath("compiler/ir/serialization.common/src/KotlinIr.proto", false),
|
||||||
|
ProtoPath("plugins/kotlin-serialization/kotlin-serialization-compiler/src/class_extensions.proto", generateDebug = false)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val EXT_OPTIONS_PROTO_PATH = ProtoPath("core/metadata/src/ext_options.proto")
|
private val EXT_OPTIONS_PROTO_PATH = ProtoPath("core/metadata/src/ext_options.proto")
|
||||||
|
|||||||
+2
-13
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
* Copyright 2010-2020 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.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.serialization.js
|
package org.jetbrains.kotlin.serialization.js
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2020 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.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ dependencies {
|
|||||||
compileOnly(project(":compiler:ir.psi2ir"))
|
compileOnly(project(":compiler:ir.psi2ir"))
|
||||||
compileOnly(project(":js:js.frontend"))
|
compileOnly(project(":js:js.frontend"))
|
||||||
compileOnly(project(":js:js.translator"))
|
compileOnly(project(":js:js.translator"))
|
||||||
|
compileOnly(project(":kotlin-util-klib-metadata"))
|
||||||
|
|
||||||
runtime(kotlinStdlib())
|
runtime(kotlinStdlib())
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.jetbrains.kotlinx.serialization.compiler.extensions;
|
||||||
|
|
||||||
|
import "core/metadata/src/metadata.proto";
|
||||||
|
import "core/metadata/src/ext_options.proto";
|
||||||
|
|
||||||
|
option java_outer_classname = "SerializationPluginMetadataExtensions";
|
||||||
|
option optimize_for = LITE_RUNTIME;
|
||||||
|
|
||||||
|
extend org.jetbrains.kotlin.metadata.Class {
|
||||||
|
repeated int32 properties_names_in_program_order = 18000;
|
||||||
|
}
|
||||||
+18
-13
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2017 JetBrains s.r.o.
|
* Copyright 2010-2020 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.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlinx.serialization.compiler.extensions
|
package org.jetbrains.kotlinx.serialization.compiler.extensions
|
||||||
@@ -27,8 +16,12 @@ import org.jetbrains.kotlin.container.useInstance
|
|||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
|
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
|
||||||
import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension
|
import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension
|
||||||
|
import org.jetbrains.kotlin.library.metadata.KlibMetadataSerializerProtocol
|
||||||
|
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
|
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
|
||||||
|
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||||
|
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SerializationPluginDeclarationChecker
|
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SerializationPluginDeclarationChecker
|
||||||
|
|
||||||
class SerializationComponentRegistrar : ComponentRegistrar {
|
class SerializationComponentRegistrar : ComponentRegistrar {
|
||||||
@@ -45,7 +38,19 @@ class SerializationComponentRegistrar : ComponentRegistrar {
|
|||||||
IrGenerationExtension.registerExtension(project, SerializationLoweringExtension())
|
IrGenerationExtension.registerExtension(project, SerializationLoweringExtension())
|
||||||
|
|
||||||
StorageComponentContainerContributor.registerExtension(project, SerializationPluginComponentContainerContributor())
|
StorageComponentContainerContributor.registerExtension(project, SerializationPluginComponentContainerContributor())
|
||||||
|
|
||||||
|
registerProtoExtensions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val serializationDescriptorSerializer = SerializationDescriptorPluginForKotlinxSerialization()
|
||||||
|
|
||||||
|
private fun registerProtoExtensions() {
|
||||||
|
DescriptorSerializer.registerSerializerPlugin(serializationDescriptorSerializer)
|
||||||
|
SerializationPluginMetadataExtensions.registerAllExtensions(JvmProtoBufUtil.EXTENSION_REGISTRY)
|
||||||
|
SerializationPluginMetadataExtensions.registerAllExtensions(JsSerializerProtocol.extensionRegistry)
|
||||||
|
SerializationPluginMetadataExtensions.registerAllExtensions(KlibMetadataSerializerProtocol.extensionRegistry)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.kotlinx.serialization.compiler.extensions
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
|
import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||||
|
import org.jetbrains.kotlin.serialization.DescriptorSerializerPlugin
|
||||||
|
import org.jetbrains.kotlin.serialization.SerializerExtension
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializableProperties
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable
|
||||||
|
|
||||||
|
class SerializationDescriptorPluginForKotlinxSerialization : DescriptorSerializerPlugin {
|
||||||
|
private val descriptorMetadataMap: MutableMap<ClassDescriptor, SerializableProperties> = hashMapOf()
|
||||||
|
|
||||||
|
private val ClassDescriptor.needSaveProgramOrder: Boolean
|
||||||
|
get() = isInternalSerializable && (modality == Modality.OPEN || modality == Modality.ABSTRACT)
|
||||||
|
|
||||||
|
internal fun putIfNeeded(descriptor: ClassDescriptor, properties: SerializableProperties) {
|
||||||
|
if (!descriptor.needSaveProgramOrder) return
|
||||||
|
descriptorMetadataMap[descriptor] = properties
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun afterClass(
|
||||||
|
descriptor: ClassDescriptor,
|
||||||
|
proto: ProtoBuf.Class.Builder,
|
||||||
|
versionRequirementTable: MutableVersionRequirementTable,
|
||||||
|
childSerializer: DescriptorSerializer,
|
||||||
|
extension: SerializerExtension
|
||||||
|
) {
|
||||||
|
fun Name.toIndex() = extension.stringTable.getStringIndex(asString())
|
||||||
|
|
||||||
|
if (!descriptor.needSaveProgramOrder) return
|
||||||
|
|
||||||
|
val propertiesCorrectOrder = (descriptorMetadataMap[descriptor] ?: return).serializableProperties
|
||||||
|
proto.setExtension(
|
||||||
|
SerializationPluginMetadataExtensions.propertiesNamesInProgramOrder,
|
||||||
|
propertiesCorrectOrder.map { it.descriptor.name.toIndex() }
|
||||||
|
)
|
||||||
|
descriptorMetadataMap.remove(descriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
// source: plugins/kotlin-serialization/kotlin-serialization-compiler/src/class_extensions.proto
|
||||||
|
|
||||||
|
package org.jetbrains.kotlinx.serialization.compiler.extensions;
|
||||||
|
|
||||||
|
public final class SerializationPluginMetadataExtensions {
|
||||||
|
private SerializationPluginMetadataExtensions() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerAllExtensions(
|
||||||
|
org.jetbrains.kotlin.protobuf.ExtensionRegistryLite registry
|
||||||
|
) {
|
||||||
|
registry.add(
|
||||||
|
org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginMetadataExtensions.propertiesNamesInProgramOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int PROPERTIES_NAMES_IN_PROGRAM_ORDER_FIELD_NUMBER = 18000;
|
||||||
|
/**
|
||||||
|
* <code>extend .org.jetbrains.kotlin.metadata.Class { ... }</code>
|
||||||
|
*/
|
||||||
|
public static final
|
||||||
|
org.jetbrains.kotlin.protobuf.GeneratedMessageLite.GeneratedExtension<
|
||||||
|
org.jetbrains.kotlin.metadata.ProtoBuf.Class,
|
||||||
|
java.util.List<java.lang.Integer>> propertiesNamesInProgramOrder = org.jetbrains.kotlin.protobuf.GeneratedMessageLite
|
||||||
|
.newRepeatedGeneratedExtension(
|
||||||
|
org.jetbrains.kotlin.metadata.ProtoBuf.Class.getDefaultInstance(),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
18000,
|
||||||
|
org.jetbrains.kotlin.protobuf.WireFormat.FieldType.INT32,
|
||||||
|
false,
|
||||||
|
java.lang.Integer.class);
|
||||||
|
|
||||||
|
static {
|
||||||
|
}
|
||||||
|
|
||||||
|
// @@protoc_insertion_point(outer_class_scope)
|
||||||
|
}
|
||||||
+23
-3
@@ -6,11 +6,17 @@
|
|||||||
package org.jetbrains.kotlinx.serialization.compiler.resolve
|
package org.jetbrains.kotlinx.serialization.compiler.resolve
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||||
import org.jetbrains.kotlin.resolve.hasBackingField
|
import org.jetbrains.kotlin.resolve.hasBackingField
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SERIALIZABLE_PROPERTIES
|
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SERIALIZABLE_PROPERTIES
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationComponentRegistrar
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginMetadataExtensions
|
||||||
|
|
||||||
class SerializableProperties(private val serializableClass: ClassDescriptor, val bindingContext: BindingContext) {
|
class SerializableProperties(private val serializableClass: ClassDescriptor, val bindingContext: BindingContext) {
|
||||||
private val primaryConstructorParameters: List<ValueParameterDescriptor> =
|
private val primaryConstructorParameters: List<ValueParameterDescriptor> =
|
||||||
@@ -44,7 +50,7 @@ class SerializableProperties(private val serializableClass: ClassDescriptor, val
|
|||||||
SerializableProperty(
|
SerializableProperty(
|
||||||
prop,
|
prop,
|
||||||
primaryConstructorProperties[prop] ?: false,
|
primaryConstructorProperties[prop] ?: false,
|
||||||
prop.hasBackingField(bindingContext)
|
prop.hasBackingField(bindingContext) || (prop is DeserializedPropertyDescriptor && prop.backingField != null) // workaround for TODO in .hasBackingField
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.filterNot { it.transient }
|
.filterNot { it.transient }
|
||||||
@@ -56,8 +62,11 @@ class SerializableProperties(private val serializableClass: ClassDescriptor, val
|
|||||||
else
|
else
|
||||||
SerializableProperties(supers, bindingContext).serializableProperties + first + second
|
SerializableProperties(supers, bindingContext).serializableProperties + first + second
|
||||||
}
|
}
|
||||||
|
.let { unsort(serializableClass, it) }
|
||||||
|
|
||||||
isExternallySerializable =
|
isExternallySerializable =
|
||||||
serializableClass.isSerializableEnum() || primaryConstructorParameters.size == primaryConstructorProperties.size
|
serializableClass.isSerializableEnum() || primaryConstructorParameters.size == primaryConstructorProperties.size
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val serializableConstructorProperties: List<SerializableProperty> =
|
val serializableConstructorProperties: List<SerializableProperty> =
|
||||||
@@ -79,5 +88,16 @@ class SerializableProperties(private val serializableClass: ClassDescriptor, val
|
|||||||
internal fun List<SerializableProperty>.bitMaskSlotCount() = size / 32 + 1
|
internal fun List<SerializableProperty>.bitMaskSlotCount() = size / 32 + 1
|
||||||
internal fun bitMaskSlotAt(propertyIndex: Int) = propertyIndex / 32
|
internal fun bitMaskSlotAt(propertyIndex: Int) = propertyIndex / 32
|
||||||
|
|
||||||
internal fun BindingContext.serializablePropertiesFor(classDescriptor: ClassDescriptor): SerializableProperties =
|
internal fun BindingContext.serializablePropertiesFor(classDescriptor: ClassDescriptor): SerializableProperties {
|
||||||
this.get(SERIALIZABLE_PROPERTIES, classDescriptor) ?: SerializableProperties(classDescriptor, this)
|
val props = this.get(SERIALIZABLE_PROPERTIES, classDescriptor) ?: SerializableProperties(classDescriptor, this)
|
||||||
|
SerializationComponentRegistrar.serializationDescriptorSerializer.putIfNeeded(classDescriptor, props)
|
||||||
|
return props
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun unsort(descriptor: ClassDescriptor, props: List<SerializableProperty>): List<SerializableProperty> {
|
||||||
|
if (descriptor !is DeserializedClassDescriptor) return props
|
||||||
|
val correctOrder: List<Name> = descriptor.classProto.getExtension(SerializationPluginMetadataExtensions.propertiesNamesInProgramOrder)
|
||||||
|
.map { descriptor.c.nameResolver.getName(it) }
|
||||||
|
val propsMap = props.associateBy { it.descriptor.name }
|
||||||
|
return correctOrder.map { propsMap.getValue(it) }
|
||||||
|
}
|
||||||
+2
-1
@@ -25,7 +25,8 @@ public class SerializationIrBytecodeListingTestGenerated extends AbstractSeriali
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInCodegen() throws Exception {
|
public void testAllFilesPresentInCodegen() throws Exception {
|
||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File(
|
||||||
|
"plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("Basic.kt")
|
@TestMetadata("Basic.kt")
|
||||||
|
|||||||
+2
-1
@@ -25,7 +25,8 @@ public class SerializationPluginBytecodeListingTestGenerated extends AbstractSer
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInCodegen() throws Exception {
|
public void testAllFilesPresentInCodegen() throws Exception {
|
||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File(
|
||||||
|
"plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("Basic.kt")
|
@TestMetadata("Basic.kt")
|
||||||
|
|||||||
+5
-13
@@ -200,7 +200,7 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
|
|||||||
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
||||||
CHECKCAST
|
CHECKCAST
|
||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
INVOKESTATIC (ListOfUsers, access$getList$p, (LListOfUsers;)Ljava/util/List;)
|
INVOKEVIRTUAL (ListOfUsers, getList, ()Ljava/util/List;)
|
||||||
INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, encodeSerializableElement, (Lkotlinx/serialization/SerialDescriptor;ILkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V)
|
INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, encodeSerializableElement, (Lkotlinx/serialization/SerialDescriptor;ILkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V)
|
||||||
ALOAD (4)
|
ALOAD (4)
|
||||||
ALOAD (3)
|
ALOAD (3)
|
||||||
@@ -302,8 +302,6 @@ public final class ListOfUsers : java/lang/Object {
|
|||||||
LABEL (L4)
|
LABEL (L4)
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static java.util.List access$getList$p(ListOfUsers $this)
|
|
||||||
|
|
||||||
public final java.util.List getList()
|
public final java.util.List getList()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,7 +486,7 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ
|
|||||||
INVOKEINTERFACE (kotlinx/serialization/Encoder, beginStructure, (Lkotlinx/serialization/SerialDescriptor;)Lkotlinx/serialization/CompositeEncoder;)
|
INVOKEINTERFACE (kotlinx/serialization/Encoder, beginStructure, (Lkotlinx/serialization/SerialDescriptor;)Lkotlinx/serialization/CompositeEncoder;)
|
||||||
ASTORE (4)
|
ASTORE (4)
|
||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
INVOKESTATIC (OptionalUser, access$getUser$p, (LOptionalUser;)LUser;)
|
INVOKEVIRTUAL (OptionalUser, getUser, ()LUser;)
|
||||||
NEW
|
NEW
|
||||||
DUP
|
DUP
|
||||||
LABEL (L2)
|
LABEL (L2)
|
||||||
@@ -515,7 +513,7 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ
|
|||||||
GETSTATIC (INSTANCE, LUser$$serializer;)
|
GETSTATIC (INSTANCE, LUser$$serializer;)
|
||||||
CHECKCAST
|
CHECKCAST
|
||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
INVOKESTATIC (OptionalUser, access$getUser$p, (LOptionalUser;)LUser;)
|
INVOKEVIRTUAL (OptionalUser, getUser, ()LUser;)
|
||||||
INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, encodeSerializableElement, (Lkotlinx/serialization/SerialDescriptor;ILkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V)
|
INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, encodeSerializableElement, (Lkotlinx/serialization/SerialDescriptor;ILkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V)
|
||||||
LABEL (L6)
|
LABEL (L6)
|
||||||
ALOAD (4)
|
ALOAD (4)
|
||||||
@@ -655,8 +653,6 @@ public final class OptionalUser : java/lang/Object {
|
|||||||
LABEL (L1)
|
LABEL (L1)
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static User access$getUser$p(OptionalUser $this)
|
|
||||||
|
|
||||||
public final User getUser()
|
public final User getUser()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -869,13 +865,13 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in
|
|||||||
ALOAD (3)
|
ALOAD (3)
|
||||||
ICONST_0
|
ICONST_0
|
||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
INVOKESTATIC (User, access$getFirstName$p, (LUser;)Ljava/lang/String;)
|
INVOKEVIRTUAL (User, getFirstName, ()Ljava/lang/String;)
|
||||||
INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, encodeStringElement, (Lkotlinx/serialization/SerialDescriptor;ILjava/lang/String;)V)
|
INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, encodeStringElement, (Lkotlinx/serialization/SerialDescriptor;ILjava/lang/String;)V)
|
||||||
ALOAD (4)
|
ALOAD (4)
|
||||||
ALOAD (3)
|
ALOAD (3)
|
||||||
ICONST_1
|
ICONST_1
|
||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
INVOKESTATIC (User, access$getLastName$p, (LUser;)Ljava/lang/String;)
|
INVOKEVIRTUAL (User, getLastName, ()Ljava/lang/String;)
|
||||||
INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, encodeStringElement, (Lkotlinx/serialization/SerialDescriptor;ILjava/lang/String;)V)
|
INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, encodeStringElement, (Lkotlinx/serialization/SerialDescriptor;ILjava/lang/String;)V)
|
||||||
ALOAD (4)
|
ALOAD (4)
|
||||||
ALOAD (3)
|
ALOAD (3)
|
||||||
@@ -1001,10 +997,6 @@ public final class User : java/lang/Object {
|
|||||||
LABEL (L6)
|
LABEL (L6)
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static java.lang.String access$getFirstName$p(User $this)
|
|
||||||
|
|
||||||
public final static java.lang.String access$getLastName$p(User $this)
|
|
||||||
|
|
||||||
public final java.lang.String getFirstName()
|
public final java.lang.String getFirstName()
|
||||||
|
|
||||||
public final java.lang.String getLastName()
|
public final java.lang.String getLastName()
|
||||||
|
|||||||
Reference in New Issue
Block a user