blob: f0da913c251b80ae67012e9ffc5dd5ed74043f2f [file] [log] [blame]
/*
* Copyright 2010-2016 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.serialization.builtins
import com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInClassDescriptorFactory
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots
import org.jetbrains.kotlin.cli.common.messages.*
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
import org.jetbrains.kotlin.cli.metadata.MetadataSerializer
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import java.io.File
class BuiltInsSerializer(dependOnOldBuiltIns: Boolean) : MetadataSerializer(BuiltInsBinaryVersion.INSTANCE, dependOnOldBuiltIns) {
fun serialize(
destDir: File,
srcDirs: List<File>,
extraClassPath: List<File>,
onComplete: (totalSize: Int, totalFiles: Int) -> Unit
) {
val rootDisposable = Disposer.newDisposable()
val messageCollector = createMessageCollector()
try {
val configuration = CompilerConfiguration().apply {
put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
addKotlinSourceRoots(srcDirs.map { it.path })
addJvmClasspathRoots(extraClassPath)
put(CLIConfigurationKeys.METADATA_DESTINATION_DIRECTORY, destDir)
put(CommonConfigurationKeys.MODULE_NAME, "module for built-ins serialization")
}
val environment = KotlinCoreEnvironment.createForTests(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
serialize(environment)
onComplete(totalSize, totalFiles)
}
finally {
messageCollector.flush()
Disposer.dispose(rootDisposable)
}
}
private fun createMessageCollector() = object : GroupingMessageCollector(
PrintingMessageCollector(System.err, MessageRenderer.PLAIN_RELATIVE_PATHS, false),
false
) {
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
// Only report diagnostics without a particular location because there's plenty of errors in built-in sources
// (functions without bodies, incorrect combination of modifiers, etc.)
if (location == null) {
super.report(severity, message, location)
}
}
}
override fun performSerialization(files: Collection<KtFile>, bindingContext: BindingContext, module: ModuleDescriptor, destDir: File) {
destDir.deleteRecursively()
if (!destDir.mkdirs()) {
throw AssertionError("Could not make directories: " + destDir)
}
files.map { it.packageFqName }.toSet().forEach {
fqName ->
val packageView = module.getPackage(fqName)
PackageSerializer(
packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) + createCloneable(module),
packageView.fragments.flatMap { fragment -> DescriptorUtils.getAllDescriptors(fragment.getMemberScope()) },
packageView.fqName,
File(destDir, BuiltInSerializerProtocol.getBuiltInsFilePath(packageView.fqName))
).run()
}
}
override fun createSerializerExtension(): KotlinSerializerExtensionBase = BuiltInsSerializerExtension()
// Serialize metadata for kotlin.Cloneable manually for compatibility with kotlin-reflect 1.0 which expects this metadata to be there.
// Since Kotlin 1.1, we always discard this class during deserialization (see ClassDeserializer.kt).
private fun createCloneable(module: ModuleDescriptor): ClassDescriptor {
val factory = JvmBuiltInClassDescriptorFactory(LockBasedStorageManager.NO_LOCKS, module) {
EmptyPackageFragmentDescriptor(module, KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME)
}
return factory.createClass(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.cloneable.toSafe()))
?: error("Could not create kotlin.Cloneable in $module")
}
}