diff --git a/.idea/modules.xml b/.idea/modules.xml index 94fd8b45917..dc0a656a7a2 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -38,6 +38,7 @@ + diff --git a/build.xml b/build.xml index 41ff53d1416..48d249c9403 100644 --- a/build.xml +++ b/build.xml @@ -117,6 +117,7 @@ + @@ -142,6 +143,7 @@ + @@ -210,6 +212,7 @@ + diff --git a/js/js.serializer/js.serializer.iml b/js/js.serializer/js.serializer.iml new file mode 100644 index 00000000000..59e4679c930 --- /dev/null +++ b/js/js.serializer/js.serializer.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/js/js.serializer/src/org/jetbrains/kotlin/utils/serializer/ClassSerializationUtil.kt b/js/js.serializer/src/org/jetbrains/kotlin/utils/serializer/ClassSerializationUtil.kt new file mode 100644 index 00000000000..4f3c814f72b --- /dev/null +++ b/js/js.serializer/src/org/jetbrains/kotlin/utils/serializer/ClassSerializationUtil.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * 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.utils.serializer + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.serialization.ProtoBuf +import org.jetbrains.kotlin.serialization.DescriptorSerializer +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor + +public object ClassSerializationUtil { + public trait Sink { + fun writeClass(classDescriptor: ClassDescriptor, classProto: ProtoBuf.Class) + } + + private fun serializeClass(classDescriptor: ClassDescriptor, serializer: DescriptorSerializer, sink: Sink, skip: (DeclarationDescriptor) -> Boolean) { + if (skip(classDescriptor)) return + + val classProto = serializer.classProto(classDescriptor).build() ?: error("Class not serialized: $classDescriptor") + sink.writeClass(classDescriptor, classProto) + + serializeClasses(classDescriptor.getUnsubstitutedInnerClassesScope().getDescriptors(), serializer, sink, skip) + } + + public fun serializeClasses(descriptors: Collection, serializer: DescriptorSerializer, sink: Sink, skip: (DeclarationDescriptor) -> Boolean) { + for (descriptor in descriptors) { + if (descriptor is ClassDescriptor) { + serializeClass(descriptor, serializer, sink, skip) + } + } + } +} \ No newline at end of file diff --git a/js/js.serializer/src/org/jetbrains/kotlin/utils/serializer/KotlinJavaScriptSerializer.kt b/js/js.serializer/src/org/jetbrains/kotlin/utils/serializer/KotlinJavaScriptSerializer.kt new file mode 100644 index 00000000000..a696487876b --- /dev/null +++ b/js/js.serializer/src/org/jetbrains/kotlin/utils/serializer/KotlinJavaScriptSerializer.kt @@ -0,0 +1,85 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * 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.utils.serializer + +import org.jetbrains.kotlin.builtins.BuiltInsSerializationUtil +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.serialization.DescriptorSerializer +import org.jetbrains.kotlin.serialization.NameSerializationUtil +import org.jetbrains.kotlin.serialization.ProtoBuf +import org.jetbrains.kotlin.serialization.builtins.BuiltInsSerializerExtension +import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil +import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils +import java.io.ByteArrayOutputStream +import java.io.File + +public class KotlinJavaScriptSerializer() { + + public fun serialize(moduleName: String, moduleDescriptor: ModuleDescriptor, metaFile: File) { + val contentMap = hashMapOf() + + DescriptorUtils.getPackagesFqNames(moduleDescriptor).forEach { + fqName -> serializePackage(moduleDescriptor, fqName) { + (fileName, stream) -> contentMap[fileName] = stream.toByteArray() + } + } + + val content = KotlinJavascriptSerializationUtil.contentMapToByteArray(contentMap) + KotlinJavascriptMetadataUtils.writeMetadata(moduleName, content, metaFile) + } + + fun serializePackage(module: ModuleDescriptor, fqName: FqName, writeFun: (String, ByteArrayOutputStream) -> Unit) { + val packageView = module.getPackage(fqName) ?: error("No package resolved in $module") + + // TODO: perform some kind of validation? At the moment not possible because DescriptorValidator is in compiler-tests + // DescriptorValidator.validate(packageView) + + val skip: (DeclarationDescriptor) -> Boolean = { DescriptorUtils.getContainingModule(it) != module} + + val serializer = DescriptorSerializer.createTopLevel(BuiltInsSerializerExtension) + + val classifierDescriptors = DescriptorSerializer.sort(packageView.getMemberScope().getDescriptors(DescriptorKindFilter.CLASSIFIERS)) + + ClassSerializationUtil.serializeClasses(classifierDescriptors, serializer, object : ClassSerializationUtil.Sink { + override fun writeClass(classDescriptor: ClassDescriptor, classProto: ProtoBuf.Class) { + val stream = ByteArrayOutputStream() + classProto.writeTo(stream) + writeFun(getFileName(classDescriptor), stream) + } + }, skip) + + val packageStream = ByteArrayOutputStream() + val fragments = module.getPackageFragmentProvider().getPackageFragments(fqName) + val packageProto = serializer.packageProto(fragments, skip).build() ?: error("Package fragments not serialized: $fragments") + packageProto.writeTo(packageStream) + writeFun(BuiltInsSerializationUtil.getPackageFilePath(fqName), packageStream) + + val nameStream = ByteArrayOutputStream() + NameSerializationUtil.serializeStringTable(nameStream, serializer.getStringTable()) + writeFun(BuiltInsSerializationUtil.getStringTableFilePath(fqName), nameStream) + } + + fun getFileName(classDescriptor: ClassDescriptor): String { + return BuiltInsSerializationUtil.getClassMetadataPath(classDescriptor.classId) + } +} \ No newline at end of file