[K2 JS] Do not load transitive dependencies for building K2/JS klibs

^KT-57262 Fixed
This commit is contained in:
Alexander Korepanov
2023-03-13 12:31:56 +01:00
committed by Space Team
parent 62fb3df7f0
commit e3402fcc87
14 changed files with 94 additions and 34 deletions
@@ -78,7 +78,7 @@ fun compileModuleToAnalyzedFir(
// TODO: !!! dependencies module data? // TODO: !!! dependencies module data?
} }
val resolvedLibraries = moduleStructure.fullResolvedLibraries val resolvedLibraries = moduleStructure.allDependencies
val sessionsWithSources = prepareJsSessions( val sessionsWithSources = prepareJsSessions(
ktFiles, moduleStructure.compilerConfiguration, escapedMainModuleName, ktFiles, moduleStructure.compilerConfiguration, escapedMainModuleName,
@@ -106,11 +106,11 @@ fun transformFirToIr(
var builtInsModule: KotlinBuiltIns? = null var builtInsModule: KotlinBuiltIns? = null
val dependencies = mutableListOf<ModuleDescriptorImpl>() val dependencies = mutableListOf<ModuleDescriptorImpl>()
val librariesDescriptors = moduleStructure.fullResolvedLibraries.map { resolvedLibrary -> val librariesDescriptors = moduleStructure.allDependencies.map { resolvedLibrary ->
val storageManager = LockBasedStorageManager("ModulesStructure") val storageManager = LockBasedStorageManager("ModulesStructure")
val moduleDescriptor = JsFactories.DefaultDeserializedDescriptorFactory.createDescriptorOptionalBuiltIns( val moduleDescriptor = JsFactories.DefaultDeserializedDescriptorFactory.createDescriptorOptionalBuiltIns(
resolvedLibrary.library, resolvedLibrary,
moduleStructure.compilerConfiguration.languageVersionSettings, moduleStructure.compilerConfiguration.languageVersionSettings,
storageManager, storageManager,
builtInsModule, builtInsModule,
@@ -120,7 +120,7 @@ fun transformFirToIr(
dependencies += moduleDescriptor dependencies += moduleDescriptor
moduleDescriptor.setDependencies(ArrayList(dependencies)) moduleDescriptor.setDependencies(ArrayList(dependencies))
val isBuiltIns = resolvedLibrary.library.unresolvedDependencies.isEmpty() val isBuiltIns = resolvedLibrary.unresolvedDependencies.isEmpty()
if (isBuiltIns) builtInsModule = moduleDescriptor.builtIns if (isBuiltIns) builtInsModule = moduleDescriptor.builtIns
moduleDescriptor moduleDescriptor
@@ -170,7 +170,7 @@ fun serializeFirKlib(
moduleStructure.compilerConfiguration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None, moduleStructure.compilerConfiguration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None,
sourceFiles, sourceFiles,
klibPath = outputKlibPath, klibPath = outputKlibPath,
moduleStructure.fullResolvedLibraries.map { it.library }, moduleStructure.allDependencies,
irResult.irModuleFragment, irResult.irModuleFragment,
expectDescriptorToSymbol = mutableMapOf(), expectDescriptorToSymbol = mutableMapOf(),
cleanFiles = icData, cleanFiles = icData,
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.session.*
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope
import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.load.kotlin.PackageAndMetadataPartProvider import org.jetbrains.kotlin.load.kotlin.PackageAndMetadataPartProvider
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -110,7 +111,7 @@ fun <F> prepareJsSessions(
files: List<F>, files: List<F>,
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
rootModuleName: Name, rootModuleName: Name,
resolvedLibraries: List<KotlinResolvedLibrary>, resolvedLibraries: List<KotlinLibrary>,
libraryList: DependencyListForCliModule, libraryList: DependencyListForCliModule,
extensionRegistrars: List<FirExtensionRegistrar>, extensionRegistrars: List<FirExtensionRegistrar>,
isCommonSource: (F) -> Boolean, isCommonSource: (F) -> Boolean,
@@ -66,7 +66,7 @@ object FirCommonSessionFactory : FirAbstractSessionFactory() {
session, session,
moduleDataProvider, moduleDataProvider,
kotlinScopeProvider, kotlinScopeProvider,
resolvedKLibs resolvedKLibs.map { it.library }
) )
}, },
FirBuiltinSymbolProvider(session, builtinsModuleData, kotlinScopeProvider), FirBuiltinSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
import org.jetbrains.kotlin.fir.scopes.impl.FirEnumEntriesSupport import org.jetbrains.kotlin.fir.scopes.impl.FirEnumEntriesSupport
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -58,7 +59,7 @@ object FirJsSessionFactory : FirAbstractSessionFactory() {
fun createLibrarySession( fun createLibrarySession(
mainModuleName: Name, mainModuleName: Name,
resolvedLibraries: List<KotlinResolvedLibrary>, resolvedLibraries: List<KotlinLibrary>,
sessionProvider: FirProjectSessionProvider, sessionProvider: FirProjectSessionProvider,
moduleDataProvider: ModuleDataProvider, moduleDataProvider: ModuleDataProvider,
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT, languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
@@ -46,7 +46,7 @@ object FirNativeSessionFactory : FirAbstractSessionFactory() {
bindSession(session) bindSession(session)
} }
listOf( listOf(
KlibBasedSymbolProvider(session, moduleDataProvider, kotlinScopeProvider, resolvedLibraries), KlibBasedSymbolProvider(session, moduleDataProvider, kotlinScopeProvider, resolvedLibraries.map { it.library }),
NativeForwardDeclarationsSymbolProvider(session, forwardDeclarationsModuleData, kotlinScopeProvider, resolvedLibraries), NativeForwardDeclarationsSymbolProvider(session, forwardDeclarationsModuleData, kotlinScopeProvider, resolvedLibraries),
FirBuiltinSymbolProvider(session, builtinsModuleData, kotlinScopeProvider), FirBuiltinSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
FirExtensionSyntheticFunctionInterfaceProvider(session, builtinsModuleData, kotlinScopeProvider), FirExtensionSyntheticFunctionInterfaceProvider(session, builtinsModuleData, kotlinScopeProvider),
@@ -15,10 +15,8 @@ import org.jetbrains.kotlin.fir.isNewPlaceForBodyGeneration
import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.library.metadata.KlibDeserializedContainerSource import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.KlibMetadataClassDataFinder import org.jetbrains.kotlin.library.metadata.*
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.library.metadata.KlibMetadataSerializerProtocol
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolver import org.jetbrains.kotlin.metadata.deserialization.NameResolver
@@ -34,17 +32,17 @@ class KlibBasedSymbolProvider(
session: FirSession, session: FirSession,
moduleDataProvider: ModuleDataProvider, moduleDataProvider: ModuleDataProvider,
kotlinScopeProvider: FirKotlinScopeProvider, kotlinScopeProvider: FirKotlinScopeProvider,
private val resolvedLibraries: Collection<KotlinResolvedLibrary>, private val resolvedLibraries: Collection<KotlinLibrary>,
defaultDeserializationOrigin: FirDeclarationOrigin = FirDeclarationOrigin.Library defaultDeserializationOrigin: FirDeclarationOrigin = FirDeclarationOrigin.Library
) : AbstractFirDeserializedSymbolProvider( ) : AbstractFirDeserializedSymbolProvider(
session, moduleDataProvider, kotlinScopeProvider, defaultDeserializationOrigin, KlibMetadataSerializerProtocol session, moduleDataProvider, kotlinScopeProvider, defaultDeserializationOrigin, KlibMetadataSerializerProtocol
) { ) {
private val moduleHeaders by lazy { private val moduleHeaders by lazy {
resolvedLibraries.associate { it to it.loadModuleHeader(it.library) } resolvedLibraries.associate { it to parseModuleHeader(it.moduleHeaderData) }
} }
private val fragmentNamesInLibraries: Map<String, List<KotlinResolvedLibrary>> by lazy { private val fragmentNamesInLibraries: Map<String, List<KotlinLibrary>> by lazy {
buildMap<String, SmartList<KotlinResolvedLibrary>> { buildMap<String, SmartList<KotlinLibrary>> {
for ((library, header) in moduleHeaders) { for ((library, header) in moduleHeaders) {
for (fragmentName in header.packageFragmentNameList) { for (fragmentName in header.packageFragmentNameList) {
getOrPut(fragmentName) { SmartList() } getOrPut(fragmentName) { SmartList() }
@@ -57,15 +55,15 @@ class KlibBasedSymbolProvider(
private val annotationDeserializer = KlibBasedAnnotationDeserializer(session) private val annotationDeserializer = KlibBasedAnnotationDeserializer(session)
private val constDeserializer = FirConstDeserializer(session, KlibMetadataSerializerProtocol) private val constDeserializer = FirConstDeserializer(session, KlibMetadataSerializerProtocol)
private val deserializationConfiguration = CompilerDeserializationConfiguration(session.languageVersionSettings) private val deserializationConfiguration = CompilerDeserializationConfiguration(session.languageVersionSettings)
private val cachedFragments = mutableMapOf<KotlinResolvedLibrary, MutableMap<Pair<String, String>, ProtoBuf.PackageFragment>>() private val cachedFragments = mutableMapOf<KotlinLibrary, MutableMap<Pair<String, String>, ProtoBuf.PackageFragment>>()
private fun getPackageFragment( private fun getPackageFragment(
resolvedLibrary: KotlinResolvedLibrary, packageStringName: String, packageMetadataPart: String resolvedLibrary: KotlinLibrary, packageStringName: String, packageMetadataPart: String
): ProtoBuf.PackageFragment { ): ProtoBuf.PackageFragment {
return cachedFragments.getOrPut(resolvedLibrary) { return cachedFragments.getOrPut(resolvedLibrary) {
mutableMapOf() mutableMapOf()
}.getOrPut(packageStringName to packageMetadataPart) { }.getOrPut(packageStringName to packageMetadataPart) {
resolvedLibrary.loadPackageFragment(resolvedLibrary.library, packageStringName, packageMetadataPart) parsePackageFragment(resolvedLibrary.packageMetadata(packageStringName, packageMetadataPart))
} }
} }
@@ -75,10 +73,10 @@ class KlibBasedSymbolProvider(
val librariesWithFragment = fragmentNamesInLibraries[packageStringName] ?: return emptyList() val librariesWithFragment = fragmentNamesInLibraries[packageStringName] ?: return emptyList()
return librariesWithFragment.flatMap { resolvedLibrary -> return librariesWithFragment.flatMap { resolvedLibrary ->
resolvedLibrary.library.packageMetadataParts(packageStringName).mapNotNull { resolvedLibrary.packageMetadataParts(packageStringName).mapNotNull {
val fragment = getPackageFragment(resolvedLibrary, packageStringName, it) val fragment = getPackageFragment(resolvedLibrary, packageStringName, it)
val libraryPath = Paths.get(resolvedLibrary.library.libraryFile.path) val libraryPath = Paths.get(resolvedLibrary.libraryFile.path)
val moduleData = moduleDataProvider.getModuleData(libraryPath) ?: return@mapNotNull null val moduleData = moduleDataProvider.getModuleData(libraryPath) ?: return@mapNotNull null
val packageProto = fragment.`package` val packageProto = fragment.`package`
@@ -117,7 +115,7 @@ class KlibBasedSymbolProvider(
val finder = KlibMetadataClassDataFinder(fragment, nameResolver) val finder = KlibMetadataClassDataFinder(fragment, nameResolver)
val classProto = finder.findClassData(classId)?.classProto ?: return@forEachFragmentInPackage val classProto = finder.findClassData(classId)?.classProto ?: return@forEachFragmentInPackage
val libraryPath = Paths.get(resolvedLibrary.library.libraryFile.path) val libraryPath = Paths.get(resolvedLibrary.libraryFile.path)
val moduleData = moduleDataProvider.getModuleData(libraryPath) ?: return null val moduleData = moduleDataProvider.getModuleData(libraryPath) ?: return null
return ClassMetadataFindResult.NoMetadata { symbol -> return ClassMetadataFindResult.NoMetadata { symbol ->
@@ -150,14 +148,14 @@ class KlibBasedSymbolProvider(
private inline fun forEachFragmentInPackage( private inline fun forEachFragmentInPackage(
packageFqName: FqName, packageFqName: FqName,
f: (KotlinResolvedLibrary, ProtoBuf.PackageFragment, NameResolver) -> Unit f: (KotlinLibrary, ProtoBuf.PackageFragment, NameResolver) -> Unit
) { ) {
val packageStringName = packageFqName.asString() val packageStringName = packageFqName.asString()
val librariesWithFragment = fragmentNamesInLibraries[packageStringName] ?: return val librariesWithFragment = fragmentNamesInLibraries[packageStringName] ?: return
for (resolvedLibrary in librariesWithFragment) { for (resolvedLibrary in librariesWithFragment) {
for (packageMetadataPart in resolvedLibrary.library.packageMetadataParts(packageStringName)) { for (packageMetadataPart in resolvedLibrary.packageMetadataParts(packageStringName)) {
val fragment = getPackageFragment(resolvedLibrary, packageStringName, packageMetadataPart) val fragment = getPackageFragment(resolvedLibrary, packageStringName, packageMetadataPart)
@@ -172,10 +170,10 @@ class KlibBasedSymbolProvider(
} }
private fun createDeserializedContainerSource( private fun createDeserializedContainerSource(
resolvedLibrary: KotlinResolvedLibrary, resolvedLibrary: KotlinLibrary,
packageFqName: FqName packageFqName: FqName
) = KlibDeserializedContainerSource( ) = KlibDeserializedContainerSource(
resolvedLibrary.library, resolvedLibrary,
moduleHeaders[resolvedLibrary]!!, moduleHeaders[resolvedLibrary]!!,
deserializationConfiguration, deserializationConfiguration,
packageFqName packageFqName
@@ -477,10 +477,6 @@ class ModulesStructure(
compilerConfiguration.get(JSConfigurationKeys.ZIP_FILE_SYSTEM_ACCESSOR) compilerConfiguration.get(JSConfigurationKeys.ZIP_FILE_SYSTEM_ACCESSOR)
) )
val fullResolvedLibraries by lazy {
allDependenciesResolution.resolveWithDependencies().getFullResolvedList()
}
val allDependencies: List<KotlinLibrary> val allDependencies: List<KotlinLibrary>
get() = allDependenciesResolution.libraries get() = allDependenciesResolution.libraries
@@ -42,7 +42,7 @@ object TestFirJsSessionFactory {
return FirJsSessionFactory.createLibrarySession( return FirJsSessionFactory.createLibrarySession(
mainModuleName, mainModuleName,
resolvedLibraries, resolvedLibraries.map { it.library },
sessionProvider, sessionProvider,
moduleDataProvider, moduleDataProvider,
languageVersionSettings, languageVersionSettings,
@@ -7138,6 +7138,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
runTest("js/js.translator/testData/box/multiModule/symbolRedeclaration.kt"); runTest("js/js.translator/testData/box/multiModule/symbolRedeclaration.kt");
} }
@Test
@TestMetadata("transitiveDependency.kt")
public void testTransitiveDependency() throws Exception {
runTest("js/js.translator/testData/box/multiModule/transitiveDependency.kt");
}
@Test @Test
@TestMetadata("useElementsFromDefaultPackageInAnotherModule.kt") @TestMetadata("useElementsFromDefaultPackageInAnotherModule.kt")
public void testUseElementsFromDefaultPackageInAnotherModule() throws Exception { public void testUseElementsFromDefaultPackageInAnotherModule() throws Exception {
@@ -7820,6 +7820,12 @@ public class FirJsBoxTestGenerated extends AbstractFirJsBoxTest {
runTest("js/js.translator/testData/box/multiModule/symbolRedeclaration.kt"); runTest("js/js.translator/testData/box/multiModule/symbolRedeclaration.kt");
} }
@Test
@TestMetadata("transitiveDependency.kt")
public void testTransitiveDependency() throws Exception {
runTest("js/js.translator/testData/box/multiModule/transitiveDependency.kt");
}
@Test @Test
@TestMetadata("useElementsFromDefaultPackageInAnotherModule.kt") @TestMetadata("useElementsFromDefaultPackageInAnotherModule.kt")
public void testUseElementsFromDefaultPackageInAnotherModule() throws Exception { public void testUseElementsFromDefaultPackageInAnotherModule() throws Exception {
@@ -7926,6 +7926,12 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test {
runTest("js/js.translator/testData/box/multiModule/symbolRedeclaration.kt"); runTest("js/js.translator/testData/box/multiModule/symbolRedeclaration.kt");
} }
@Test
@TestMetadata("transitiveDependency.kt")
public void testTransitiveDependency() throws Exception {
runTest("js/js.translator/testData/box/multiModule/transitiveDependency.kt");
}
@Test @Test
@TestMetadata("useElementsFromDefaultPackageInAnotherModule.kt") @TestMetadata("useElementsFromDefaultPackageInAnotherModule.kt")
public void testUseElementsFromDefaultPackageInAnotherModule() throws Exception { public void testUseElementsFromDefaultPackageInAnotherModule() throws Exception {
@@ -7820,6 +7820,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
runTest("js/js.translator/testData/box/multiModule/symbolRedeclaration.kt"); runTest("js/js.translator/testData/box/multiModule/symbolRedeclaration.kt");
} }
@Test
@TestMetadata("transitiveDependency.kt")
public void testTransitiveDependency() throws Exception {
runTest("js/js.translator/testData/box/multiModule/transitiveDependency.kt");
}
@Test @Test
@TestMetadata("useElementsFromDefaultPackageInAnotherModule.kt") @TestMetadata("useElementsFromDefaultPackageInAnotherModule.kt")
public void testUseElementsFromDefaultPackageInAnotherModule() throws Exception { public void testUseElementsFromDefaultPackageInAnotherModule() throws Exception {
@@ -0,0 +1,15 @@
// KJS_WITH_FULL_RUNTIME
// MODULE: lib1
// FILE: lib1.kt
fun module1() = "K"
// MODULE: lib2(lib1)
// FILE: lib2.kt
fun module2() = "O" + module1()
// MODULE: main(lib2)
// FILE: main.kt
fun box() = module2()
@@ -385,9 +385,9 @@ class Kotlin2JsIrGradlePluginIT : AbstractKotlin2JsGradlePluginIT(true) {
} }
} }
@DisplayName("JS IR implementation dependency") @DisplayName("K1/JS IR implementation dependency")
@GradleTest @GradleTest
fun testJsIrImplementationDependency(gradleVersion: GradleVersion) { fun testK1JsIrImplementationDependency(gradleVersion: GradleVersion) {
project("kotlin-js-browser-project", gradleVersion) { project("kotlin-js-browser-project", gradleVersion) {
buildGradleKts.modify(::transformBuildScriptWithPluginsDsl) buildGradleKts.modify(::transformBuildScriptWithPluginsDsl)
@@ -401,6 +401,31 @@ class Kotlin2JsIrGradlePluginIT : AbstractKotlin2JsGradlePluginIT(true) {
} }
} }
@DisplayName("K2/JS IR implementation dependency")
@GradleTest
fun testK2JsIrImplementationDependency(gradleVersion: GradleVersion) {
project("kotlin-js-browser-project", gradleVersion) {
buildGradleKts.modify(::transformBuildScriptWithPluginsDsl)
buildGradleKts.append(
"""
rootProject.subprojects.forEach {
it.tasks.withType<org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile> {
kotlinOptions.languageVersion = "2.0"
}
}
""".trimIndent()
)
build(":app:compileProductionExecutableKotlinJs")
projectPath.resolve("app/src/main/kotlin/App.kt").modify {
it.replace("sheldon()", "best()")
}
buildAndFail(":app:compileProductionExecutableKotlinJs")
}
}
@DisplayName("JS IR compiled against automatically added dom-api-compat") @DisplayName("JS IR compiled against automatically added dom-api-compat")
@GradleTest @GradleTest
fun testJsIrCompiledAgainstAutomaticallyAddedDomApiCompat(gradleVersion: GradleVersion) { fun testJsIrCompiledAgainstAutomaticallyAddedDomApiCompat(gradleVersion: GradleVersion) {