Simplify code in JS serialization related to module descriptors

Do not use `JsModuleDescriptor<...>` where only its `data` is needed
This commit is contained in:
Alexander Udalov
2018-07-11 19:32:19 +02:00
parent 77405b2cca
commit ae6627fe94
9 changed files with 79 additions and 134 deletions
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.ir.backend.js.lower.*
import org.jetbrains.kotlin.ir.backend.js.lower.inline.*
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
@@ -23,8 +22,6 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor
import org.jetbrains.kotlin.serialization.js.ModuleKind
data class Result(val moduleDescriptor: ModuleDescriptor, val generatedCode: String)
@@ -35,12 +32,8 @@ fun compile(
export: FqName? = null,
dependencies: List<ModuleDescriptor> = listOf()
): Result {
val moduleDescriptors =
dependencies
.filterIsInstance<ModuleDescriptorImpl>()
.map { JsModuleDescriptor("", ModuleKind.PLAIN, listOf(), it) }
val analysisResult = TopDownAnalyzerFacadeForJS.analyzeFiles(files, project, configuration, moduleDescriptors, emptyList())
val analysisResult =
TopDownAnalyzerFacadeForJS.analyzeFiles(files, project, configuration, dependencies.filterIsInstance(), emptyList())
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
@@ -77,7 +77,7 @@ abstract class AbstractDiagnosticsTestWithJsStdLib : AbstractDiagnosticsTest() {
}
override fun getAdditionalDependencies(module: ModuleDescriptorImpl): List<ModuleDescriptorImpl> =
config.moduleDescriptors.map { it.data }
config.moduleDescriptors
override fun shouldSkipJvmSignatureDiagnostics(groupedByModule: Map<TestModule?, List<TestFile>>): Boolean = true
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.js.config.JsConfig
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil.TEST_PACKAGE_FQNAME
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil.readModuleAsProto
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
@@ -94,9 +95,10 @@ class KotlinJavascriptSerializerTest : TestCaseWithTmpdir() {
val metadata = KotlinJavascriptMetadataUtils.loadMetadata(metaFile)
assert(metadata.size == 1)
val provider = KotlinJavascriptSerializationUtil.readModule(
metadata.single().body, LockBasedStorageManager(), module, DeserializationConfiguration.Default, LookupTracker.DO_NOTHING
).data.sure { "No package fragment provider was created" }
val (header, packageFragmentProtos) = readModuleAsProto(metadata.single().body)
val provider = createKotlinJavascriptPackageFragmentProvider(
LockBasedStorageManager(), module, header, packageFragmentProtos, DeserializationConfiguration.Default, LookupTracker.DO_NOTHING
).sure { "No package fragment provider was created" }
module.initialize(provider)
module.setDependencies(module, module.builtIns.builtInsModule)
@@ -32,8 +32,8 @@ import org.jetbrains.kotlin.resolve.TargetEnvironment
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
import org.jetbrains.kotlin.serialization.js.createKotlinJavascriptPackageFragmentProvider
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
object JsAnalyzerFacade : ResolverForModuleFactory() {
@@ -72,11 +72,12 @@ object JsAnalyzerFacade : ResolverForModuleFactory() {
val providers = moduleInfo.getLibraryRoots()
.flatMap { KotlinJavascriptMetadataUtils.loadMetadata(it) }
.filter { it.version.isCompatible() }
.mapNotNull {
KotlinJavascriptSerializationUtil.readModule(
it.body, moduleContext.storageManager, moduleDescriptor, container.get<DeserializationConfiguration>(),
LookupTracker.DO_NOTHING
).data
.map { metadata ->
val (header, packageFragmentProtos) = KotlinJavascriptSerializationUtil.readModuleAsProto(metadata.body)
createKotlinJavascriptPackageFragmentProvider(
moduleContext.storageManager, moduleDescriptor, header, packageFragmentProtos,
container.get(), LookupTracker.DO_NOTHING
)
}
if (providers.isNotEmpty()) {
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
import org.jetbrains.kotlin.serialization.js.ModuleKind
import org.jetbrains.kotlin.serialization.js.PackagesWithHeaderMetadata
@@ -56,8 +55,8 @@ object TopDownAnalyzerFacadeForJS {
files: Collection<KtFile>,
project: Project,
configuration: CompilerConfiguration,
moduleDescriptors: List<JsModuleDescriptor<ModuleDescriptorImpl>>,
friendModuleDescriptors: List<JsModuleDescriptor<ModuleDescriptorImpl>>
moduleDescriptors: List<ModuleDescriptorImpl>,
friendModuleDescriptors: List<ModuleDescriptorImpl>
): JsAnalysisResult {
val moduleName = configuration[CommonConfigurationKeys.MODULE_NAME]!!
@@ -65,9 +64,9 @@ object TopDownAnalyzerFacadeForJS {
context.module.setDependencies(
listOf(context.module) +
moduleDescriptors.map { it.data } +
moduleDescriptors +
listOf(JsPlatform.builtIns.builtInsModule),
friendModuleDescriptors.map { it.data }.toSet()
friendModuleDescriptors.toSet()
)
val moduleKind = configuration.get(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
@@ -33,10 +33,7 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker;
import org.jetbrains.kotlin.js.resolve.JsPlatform;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration;
import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor;
import org.jetbrains.kotlin.serialization.js.KotlinJavaScriptLibraryParts;
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil;
import org.jetbrains.kotlin.serialization.js.ModuleKind;
import org.jetbrains.kotlin.serialization.js.*;
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
import org.jetbrains.kotlin.utils.JsMetadataVersion;
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata;
@@ -64,11 +61,8 @@ public class JsConfig {
private final List<KotlinJavascriptMetadata> metadata = new SmartList<>();
private final List<KotlinJavascriptMetadata> friends = new SmartList<>();
@Nullable
private List<JsModuleDescriptor<ModuleDescriptorImpl>> moduleDescriptors = null;
@Nullable
private List<JsModuleDescriptor<ModuleDescriptorImpl>> friendModuleDescriptors = null;
private List<ModuleDescriptorImpl> moduleDescriptors;
private List<ModuleDescriptorImpl> friendModuleDescriptors;
private boolean initialized = false;
@@ -237,19 +231,16 @@ public class JsConfig {
}
@NotNull
public List<JsModuleDescriptor<ModuleDescriptorImpl>> getModuleDescriptors() {
public List<ModuleDescriptorImpl> getModuleDescriptors() {
init();
return moduleDescriptors;
}
@NotNull
private List<JsModuleDescriptor<ModuleDescriptorImpl>> createModuleDescriptors() {
List<JsModuleDescriptor<ModuleDescriptorImpl>> moduleDescriptors = new SmartList<>();
List<ModuleDescriptorImpl> kotlinModuleDescriptors = new ArrayList<>();
private List<ModuleDescriptorImpl> createModuleDescriptors() {
List<ModuleDescriptorImpl> moduleDescriptors = new SmartList<>();
for (KotlinJavascriptMetadata metadataEntry : metadata) {
JsModuleDescriptor<ModuleDescriptorImpl> descriptor = createModuleDescriptor(metadataEntry);
moduleDescriptors.add(descriptor);
kotlinModuleDescriptors.add(descriptor.getData());
moduleDescriptors.add(createModuleDescriptor(metadataEntry));
}
if (metadataCache != null) {
@@ -259,50 +250,30 @@ public class JsConfig {
Name.special("<" + cached.getName() + ">"), storageManager, JsPlatform.INSTANCE.getBuiltIns()
);
JsModuleDescriptor<PackageFragmentProvider> rawDescriptor = KotlinJavascriptSerializationUtil.readModuleFromProto(
cached, storageManager, moduleDescriptor,
PackageFragmentProvider provider = KotlinJavascriptPackageFragmentProviderKt.createKotlinJavascriptPackageFragmentProvider(
storageManager, moduleDescriptor, cached.getData().getHeader(), cached.getData().getBody(),
new CompilerDeserializationConfiguration(languageVersionSettings),
LookupTracker.DO_NOTHING.INSTANCE
);
PackageFragmentProvider provider = rawDescriptor.getData();
moduleDescriptor.initialize(provider != null ? provider : PackageFragmentProvider.Empty.INSTANCE);
JsModuleDescriptor<ModuleDescriptorImpl> jsModuleDescriptor = cached.copy(moduleDescriptor);
moduleDescriptors.add(jsModuleDescriptor);
kotlinModuleDescriptors.add(jsModuleDescriptor.getData());
moduleDescriptor.initialize(provider);
moduleDescriptors.add(moduleDescriptor);
}
}
for (JsModuleDescriptor<ModuleDescriptorImpl> module : moduleDescriptors) {
// TODO: remove downcast
setDependencies(module.getData(), kotlinModuleDescriptors);
for (ModuleDescriptorImpl module : moduleDescriptors) {
setDependencies(module, moduleDescriptors);
}
moduleDescriptors = Collections.unmodifiableList(moduleDescriptors);
return moduleDescriptors;
return Collections.unmodifiableList(moduleDescriptors);
}
@NotNull
public List<JsModuleDescriptor<ModuleDescriptorImpl>> getFriendModuleDescriptors() {
public List<ModuleDescriptorImpl> getFriendModuleDescriptors() {
init();
return friendModuleDescriptors;
}
@NotNull
private List<JsModuleDescriptor<ModuleDescriptorImpl>> createFriendModuleDescriptors() {
List<JsModuleDescriptor<ModuleDescriptorImpl>> friendModuleDescriptors = new SmartList<>();
for (KotlinJavascriptMetadata metadataEntry : friends) {
JsModuleDescriptor<ModuleDescriptorImpl> descriptor = createModuleDescriptor(metadataEntry);
friendModuleDescriptors.add(descriptor);
}
friendModuleDescriptors = Collections.unmodifiableList(friendModuleDescriptors);
return friendModuleDescriptors;
}
public void init() {
if (!initialized) {
JsConfig.Reporter reporter = new Reporter() {
@@ -320,13 +291,13 @@ public class JsConfig {
}
if (friendModuleDescriptors == null) {
friendModuleDescriptors = createFriendModuleDescriptors();
friendModuleDescriptors = CollectionsKt.map(friends, this::createModuleDescriptor);
}
}
private final IdentityHashMap<KotlinJavascriptMetadata, JsModuleDescriptor<ModuleDescriptorImpl>> factoryMap = new IdentityHashMap<>();
private final IdentityHashMap<KotlinJavascriptMetadata, ModuleDescriptorImpl> factoryMap = new IdentityHashMap<>();
private JsModuleDescriptor<ModuleDescriptorImpl> createModuleDescriptor(KotlinJavascriptMetadata metadata) {
private ModuleDescriptorImpl createModuleDescriptor(KotlinJavascriptMetadata metadata) {
return factoryMap.computeIfAbsent(metadata, m -> {
LanguageVersionSettings languageVersionSettings = CommonConfigurationKeysKt.getLanguageVersionSettings(configuration);
assert m.getVersion().isCompatible() ||
@@ -338,16 +309,15 @@ public class JsConfig {
);
LookupTracker lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER, LookupTracker.DO_NOTHING.INSTANCE);
JsModuleDescriptor<PackageFragmentProvider> rawDescriptor = KotlinJavascriptSerializationUtil.readModule(
m.getBody(), storageManager, moduleDescriptor,
KotlinJavaScriptLibraryParts parts = KotlinJavascriptSerializationUtil.readModuleAsProto(m.getBody());
PackageFragmentProvider provider = KotlinJavascriptPackageFragmentProviderKt.createKotlinJavascriptPackageFragmentProvider(
storageManager, moduleDescriptor, parts.getHeader(), parts.getBody(),
new CompilerDeserializationConfiguration(languageVersionSettings),
lookupTracker
);
PackageFragmentProvider provider = rawDescriptor.getData();
moduleDescriptor.initialize(provider != null ? provider : PackageFragmentProvider.Empty.INSTANCE);
return rawDescriptor.copy(moduleDescriptor);
moduleDescriptor.initialize(provider);
return moduleDescriptor;
});
}
@@ -16,6 +16,9 @@
package org.jetbrains.kotlin.serialization.js
class JsModuleDescriptor<out T>(val name: String, val kind: ModuleKind, val imported: List<String>, val data: T) {
fun <S> copy(newData: S) = JsModuleDescriptor(name, kind, imported, newData)
}
class JsModuleDescriptor<out T>(
val name: String,
val kind: ModuleKind,
val imported: List<String>,
val data: T
)
@@ -51,34 +51,6 @@ import java.util.zip.GZIPOutputStream
object KotlinJavascriptSerializationUtil {
const val CLASS_METADATA_FILE_EXTENSION: String = "kjsm"
@JvmStatic
fun readModule(
metadata: ByteArray,
storageManager: StorageManager,
module: ModuleDescriptor,
configuration: DeserializationConfiguration,
lookupTracker: LookupTracker
): JsModuleDescriptor<PackageFragmentProvider?> =
readModuleFromProto(readModuleAsProto(metadata, module.name.asString()), storageManager, module, configuration, lookupTracker)
fun readModuleAsProto(metadata: ByteArray, name: String): JsModuleDescriptor<KotlinJavaScriptLibraryParts> =
metadata.deserializeToLibraryParts(name)
@JvmStatic
fun readModuleFromProto(
jsModule: JsModuleDescriptor<KotlinJavaScriptLibraryParts>,
storageManager: StorageManager, module: ModuleDescriptor,
configuration: DeserializationConfiguration,
lookupTracker: LookupTracker
): JsModuleDescriptor<PackageFragmentProvider?> {
val (header, packageFragmentProtos) = jsModule.data
return jsModule.copy(
createKotlinJavascriptPackageFragmentProvider(
storageManager, module, header, packageFragmentProtos, configuration, lookupTracker
)
)
}
fun readDescriptors(
metadata: PackagesWithHeaderMetadata,
storageManager: StorageManager,
@@ -334,27 +306,30 @@ object KotlinJavascriptSerializationUtil {
}
}
private fun ByteArray.deserializeToLibraryParts(name: String): JsModuleDescriptor<KotlinJavaScriptLibraryParts> {
val (header, content) = GZIPInputStream(ByteArrayInputStream(this)).use { stream ->
@JvmStatic
fun readModuleAsProto(metadata: ByteArray): KotlinJavaScriptLibraryParts {
val (header, content) = GZIPInputStream(ByteArrayInputStream(metadata)).use { stream ->
JsProtoBuf.Header.parseDelimitedFrom(stream, JsSerializerProtocol.extensionRegistry) to
JsProtoBuf.Library.parseFrom(stream, JsSerializerProtocol.extensionRegistry)
}
return JsModuleDescriptor(
name = name,
data = KotlinJavaScriptLibraryParts(header, content.packageFragmentList),
kind = when (content.kind) {
null, JsProtoBuf.Library.Kind.PLAIN -> ModuleKind.PLAIN
JsProtoBuf.Library.Kind.AMD -> ModuleKind.AMD
JsProtoBuf.Library.Kind.COMMON_JS -> ModuleKind.COMMON_JS
JsProtoBuf.Library.Kind.UMD -> ModuleKind.UMD
},
imported = content.importedModuleList
)
val moduleKind = when (content.kind) {
null, JsProtoBuf.Library.Kind.PLAIN -> ModuleKind.PLAIN
JsProtoBuf.Library.Kind.AMD -> ModuleKind.AMD
JsProtoBuf.Library.Kind.COMMON_JS -> ModuleKind.COMMON_JS
JsProtoBuf.Library.Kind.UMD -> ModuleKind.UMD
}
return KotlinJavaScriptLibraryParts(header, content.packageFragmentList, moduleKind, content.importedModuleList)
}
}
data class KotlinJavaScriptLibraryParts(val header: JsProtoBuf.Header, val body: List<ProtoBuf.PackageFragment>)
data class KotlinJavaScriptLibraryParts(
val header: JsProtoBuf.Header,
val body: List<ProtoBuf.PackageFragment>,
val kind: ModuleKind,
val importedModules: List<String>
)
internal fun DeclarationDescriptor.extractFileId(): Int? = when (this) {
is DeserializedClassDescriptor -> classProto.getExtension(JsProtoBuf.classContainingFileId)
@@ -49,6 +49,7 @@ import org.jetbrains.kotlin.metadata.DebugProtoBuf
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
import org.jetbrains.kotlin.serialization.js.ModuleKind
@@ -394,9 +395,11 @@ abstract class BasicBoxTest(
val originalMetadata = FileUtil.loadFile(File(outputFile.parentFile, outputFile.nameWithoutExtension + ".meta.js"))
val recompiledMetadata = removeRecompiledSuffix(
FileUtil.loadFile(File(recompiledOutputFile.parentFile, recompiledOutputFile.nameWithoutExtension + ".meta.js")))
assertEquals("Metadata file changed after recompilation",
metadataAsString(originalMetadata, module.name),
metadataAsString(recompiledMetadata, module.name))
assertEquals(
"Metadata file changed after recompilation",
metadataAsString(originalMetadata),
metadataAsString(recompiledMetadata)
)
}
}
@@ -406,10 +409,10 @@ abstract class BasicBoxTest(
return String(out.toByteArray(), Charset.forName("UTF-8"))
}
private fun metadataAsString(metadata: String, moduleName: String): String {
private fun metadataAsString(metadata: String): String {
val containers = mutableListOf<KotlinJavascriptMetadata>()
KotlinJavascriptMetadataUtils.parseMetadata(metadata, containers)
val metadataParts = KotlinJavascriptSerializationUtil.readModuleAsProto(containers.single().body, moduleName).data.body
val metadataParts = KotlinJavascriptSerializationUtil.readModuleAsProto(containers.single().body).body
return metadataParts.joinToString("-----\n") {
val binary = it.toByteArray()
DebugProtoBuf.PackageFragment.parseFrom(binary, JsSerializerProtocol.extensionRegistry).toString()
@@ -738,13 +741,12 @@ abstract class BasicBoxTest(
KotlinCoreEnvironment.createForTests(testRootDisposable, CompilerConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES)
companion object {
val METADATA_CACHE = (JsConfig.JS_STDLIB.asSequence() + JsConfig.JS_KOTLIN_TEST)
.flatMap {
KotlinJavascriptMetadataUtils
.loadMetadata(it).asSequence()
.map { KotlinJavascriptSerializationUtil.readModuleAsProto(it.body, it.moduleName) }
}
.toList()
val METADATA_CACHE = (JsConfig.JS_STDLIB + JsConfig.JS_KOTLIN_TEST).flatMap { path ->
KotlinJavascriptMetadataUtils.loadMetadata(path).map { metadata ->
val parts = KotlinJavascriptSerializationUtil.readModuleAsProto(metadata.body)
JsModuleDescriptor(metadata.moduleName, parts.kind, parts.importedModules, parts)
}
}
const val TEST_DATA_DIR_PATH = "js/js.translator/testData/"
const val DIST_DIR_JS_PATH = "dist/js/"