K2 scripting: separate scripts compilation into another session
when scripts are compiled along with other sources. #KT-65865 fixed
This commit is contained in:
committed by
Space Team
parent
3ce2172c79
commit
e5a6900458
@@ -8,10 +8,7 @@ package org.jetbrains.kotlin.cli.common
|
|||||||
import org.jetbrains.kotlin.KtSourceFile
|
import org.jetbrains.kotlin.KtSourceFile
|
||||||
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
|
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
|
||||||
import org.jetbrains.kotlin.config.*
|
import org.jetbrains.kotlin.config.*
|
||||||
import org.jetbrains.kotlin.fir.DependencyListForCliModule
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.FirModuleData
|
|
||||||
import org.jetbrains.kotlin.fir.FirModuleDataImpl
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.OptInLanguageVersionSettingsCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.OptInLanguageVersionSettingsCheckers
|
||||||
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
|
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
||||||
@@ -68,6 +65,7 @@ fun <F> prepareJvmSessions(
|
|||||||
librariesScope: AbstractProjectFileSearchScope,
|
librariesScope: AbstractProjectFileSearchScope,
|
||||||
libraryList: DependencyListForCliModule,
|
libraryList: DependencyListForCliModule,
|
||||||
isCommonSource: (F) -> Boolean,
|
isCommonSource: (F) -> Boolean,
|
||||||
|
isScript: (F) -> Boolean,
|
||||||
fileBelongsToModule: (F, String) -> Boolean,
|
fileBelongsToModule: (F, String) -> Boolean,
|
||||||
createProviderAndScopeForIncrementalCompilation: (List<F>) -> IncrementalCompilationContext?,
|
createProviderAndScopeForIncrementalCompilation: (List<F>) -> IncrementalCompilationContext?,
|
||||||
): List<SessionWithSources<F>> {
|
): List<SessionWithSources<F>> {
|
||||||
@@ -79,7 +77,7 @@ fun <F> prepareJvmSessions(
|
|||||||
|
|
||||||
return prepareSessions(
|
return prepareSessions(
|
||||||
files, configuration, rootModuleName, JvmPlatforms.unspecifiedJvmPlatform,
|
files, configuration, rootModuleName, JvmPlatforms.unspecifiedJvmPlatform,
|
||||||
JvmPlatformAnalyzerServices, metadataCompilationMode = false, libraryList, isCommonSource, fileBelongsToModule,
|
JvmPlatformAnalyzerServices, metadataCompilationMode = false, libraryList, isCommonSource, isScript, fileBelongsToModule,
|
||||||
createLibrarySession = { sessionProvider ->
|
createLibrarySession = { sessionProvider ->
|
||||||
FirJvmSessionFactory.createLibrarySession(
|
FirJvmSessionFactory.createLibrarySession(
|
||||||
rootModuleName,
|
rootModuleName,
|
||||||
@@ -149,7 +147,8 @@ fun <F> prepareJsSessions(
|
|||||||
): List<SessionWithSources<F>> {
|
): List<SessionWithSources<F>> {
|
||||||
return prepareSessions(
|
return prepareSessions(
|
||||||
files, configuration, rootModuleName, JsPlatforms.defaultJsPlatform, JsPlatformAnalyzerServices,
|
files, configuration, rootModuleName, JsPlatforms.defaultJsPlatform, JsPlatformAnalyzerServices,
|
||||||
metadataCompilationMode = false, libraryList, isCommonSource, fileBelongsToModule,
|
metadataCompilationMode = false, libraryList, isCommonSource, isScript = { false },
|
||||||
|
fileBelongsToModule,
|
||||||
createLibrarySession = { sessionProvider ->
|
createLibrarySession = { sessionProvider ->
|
||||||
FirJsSessionFactory.createLibrarySession(
|
FirJsSessionFactory.createLibrarySession(
|
||||||
rootModuleName,
|
rootModuleName,
|
||||||
@@ -196,7 +195,8 @@ fun <F> prepareNativeSessions(
|
|||||||
): List<SessionWithSources<F>> {
|
): List<SessionWithSources<F>> {
|
||||||
return prepareSessions(
|
return prepareSessions(
|
||||||
files, configuration, rootModuleName, NativePlatforms.unspecifiedNativePlatform, NativePlatformAnalyzerServices,
|
files, configuration, rootModuleName, NativePlatforms.unspecifiedNativePlatform, NativePlatformAnalyzerServices,
|
||||||
metadataCompilationMode, libraryList, isCommonSource, fileBelongsToModule, createLibrarySession = { sessionProvider ->
|
metadataCompilationMode, libraryList, isCommonSource, isScript = { false },
|
||||||
|
fileBelongsToModule, createLibrarySession = { sessionProvider ->
|
||||||
FirNativeSessionFactory.createLibrarySession(
|
FirNativeSessionFactory.createLibrarySession(
|
||||||
rootModuleName,
|
rootModuleName,
|
||||||
resolvedLibraries,
|
resolvedLibraries,
|
||||||
@@ -244,7 +244,8 @@ fun <F> prepareWasmSessions(
|
|||||||
}
|
}
|
||||||
return prepareSessions(
|
return prepareSessions(
|
||||||
files, configuration, rootModuleName, WasmPlatforms.Default, analyzerServices,
|
files, configuration, rootModuleName, WasmPlatforms.Default, analyzerServices,
|
||||||
metadataCompilationMode = false, libraryList, isCommonSource, fileBelongsToModule,
|
metadataCompilationMode = false, libraryList, isCommonSource, isScript = { false },
|
||||||
|
fileBelongsToModule,
|
||||||
createLibrarySession = { sessionProvider ->
|
createLibrarySession = { sessionProvider ->
|
||||||
FirWasmSessionFactory.createLibrarySession(
|
FirWasmSessionFactory.createLibrarySession(
|
||||||
rootModuleName,
|
rootModuleName,
|
||||||
@@ -291,7 +292,8 @@ fun <F> prepareCommonSessions(
|
|||||||
): List<SessionWithSources<F>> {
|
): List<SessionWithSources<F>> {
|
||||||
return prepareSessions(
|
return prepareSessions(
|
||||||
files, configuration, rootModuleName, CommonPlatforms.defaultCommonPlatform, CommonPlatformAnalyzerServices,
|
files, configuration, rootModuleName, CommonPlatforms.defaultCommonPlatform, CommonPlatformAnalyzerServices,
|
||||||
metadataCompilationMode = true, libraryList, isCommonSource, fileBelongsToModule, createLibrarySession = { sessionProvider ->
|
metadataCompilationMode = true, libraryList, isCommonSource, isScript = { false }, fileBelongsToModule,
|
||||||
|
createLibrarySession = { sessionProvider ->
|
||||||
FirCommonSessionFactory.createLibrarySession(
|
FirCommonSessionFactory.createLibrarySession(
|
||||||
rootModuleName,
|
rootModuleName,
|
||||||
sessionProvider,
|
sessionProvider,
|
||||||
@@ -335,11 +337,13 @@ private inline fun <F> prepareSessions(
|
|||||||
metadataCompilationMode: Boolean,
|
metadataCompilationMode: Boolean,
|
||||||
libraryList: DependencyListForCliModule,
|
libraryList: DependencyListForCliModule,
|
||||||
isCommonSource: (F) -> Boolean,
|
isCommonSource: (F) -> Boolean,
|
||||||
|
isScript: (F) -> Boolean,
|
||||||
fileBelongsToModule: (F, String) -> Boolean,
|
fileBelongsToModule: (F, String) -> Boolean,
|
||||||
createLibrarySession: (FirProjectSessionProvider) -> FirSession,
|
createLibrarySession: (FirProjectSessionProvider) -> FirSession,
|
||||||
createSourceSession: FirSessionProducer<F>,
|
createSourceSession: FirSessionProducer<F>,
|
||||||
): List<SessionWithSources<F>> {
|
): List<SessionWithSources<F>> {
|
||||||
val languageVersionSettings = configuration.languageVersionSettings
|
val languageVersionSettings = configuration.languageVersionSettings
|
||||||
|
val (scripts, nonScriptFiles) = files.partition(isScript)
|
||||||
|
|
||||||
val isMppEnabled = languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)
|
val isMppEnabled = languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)
|
||||||
val hmppModuleStructure = configuration.get(CommonConfigurationKeys.HMPP_MODULE_STRUCTURE)
|
val hmppModuleStructure = configuration.get(CommonConfigurationKeys.HMPP_MODULE_STRUCTURE)
|
||||||
@@ -353,26 +357,58 @@ private inline fun <F> prepareSessions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return when {
|
val nonScriptSessions =when {
|
||||||
metadataCompilationMode || !isMppEnabled -> listOf(
|
metadataCompilationMode || !isMppEnabled -> {
|
||||||
createSingleSession(
|
listOf(
|
||||||
files, rootModuleName, libraryList, targetPlatform, analyzerServices,
|
createSingleSession(
|
||||||
sessionProvider, sessionConfigurator, createSourceSession
|
nonScriptFiles, rootModuleName, libraryList, targetPlatform, analyzerServices,
|
||||||
|
sessionProvider, sessionConfigurator, createSourceSession
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
|
|
||||||
hmppModuleStructure == null -> createSessionsForLegacyMppProject(
|
hmppModuleStructure == null -> createSessionsForLegacyMppProject(
|
||||||
files, rootModuleName, libraryList, targetPlatform, analyzerServices,
|
nonScriptFiles, rootModuleName, libraryList, targetPlatform, analyzerServices,
|
||||||
sessionProvider, sessionConfigurator, isCommonSource, createSourceSession
|
sessionProvider, sessionConfigurator, isCommonSource, createSourceSession
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> createSessionsForHmppProject(
|
else -> createSessionsForHmppProject(
|
||||||
files, rootModuleName, hmppModuleStructure, libraryList, targetPlatform, analyzerServices,
|
nonScriptFiles, rootModuleName, hmppModuleStructure, libraryList, targetPlatform, analyzerServices,
|
||||||
sessionProvider, sessionConfigurator, fileBelongsToModule, createSourceSession
|
sessionProvider, sessionConfigurator, fileBelongsToModule, createSourceSession
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return if (scripts.isEmpty()) nonScriptSessions
|
||||||
|
else nonScriptSessions +
|
||||||
|
createScriptsSession(
|
||||||
|
scripts, rootModuleName, libraryList, nonScriptSessions.last().session.moduleData,
|
||||||
|
targetPlatform, analyzerServices, sessionProvider, sessionConfigurator, createSourceSession
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline fun <F> createScriptsSession(
|
||||||
|
scripts: List<F>,
|
||||||
|
rootModuleName: Name,
|
||||||
|
libraryList: DependencyListForCliModule,
|
||||||
|
lastModuleData: FirModuleData,
|
||||||
|
targetPlatform: TargetPlatform,
|
||||||
|
analyzerServices: PlatformDependentAnalyzerServices,
|
||||||
|
sessionProvider: FirProjectSessionProvider,
|
||||||
|
noinline sessionConfigurator: FirSessionConfigurator.() -> Unit,
|
||||||
|
createSourceSession: FirSessionProducer<F>,
|
||||||
|
): SessionWithSources<F> =
|
||||||
|
createSingleSession(
|
||||||
|
scripts, Name.identifier("${rootModuleName.asString()}-scripts"),
|
||||||
|
DependencyListForCliModule(
|
||||||
|
libraryList.regularDependencies,
|
||||||
|
listOf(lastModuleData),
|
||||||
|
libraryList.friendsDependencies,
|
||||||
|
libraryList.moduleDataProvider
|
||||||
|
),
|
||||||
|
targetPlatform, analyzerServices,
|
||||||
|
sessionProvider, sessionConfigurator, createSourceSession
|
||||||
|
)
|
||||||
|
|
||||||
private inline fun <F> createSingleSession(
|
private inline fun <F> createSingleSession(
|
||||||
files: List<F>,
|
files: List<F>,
|
||||||
rootModuleName: Name,
|
rootModuleName: Name,
|
||||||
|
|||||||
+1
@@ -214,6 +214,7 @@ object FirKotlinToJvmBytecodeCompiler {
|
|||||||
ktFiles, configuration, projectEnvironment, Name.special("<$rootModuleName>"),
|
ktFiles, configuration, projectEnvironment, Name.special("<$rootModuleName>"),
|
||||||
extensionRegistrars, librariesScope, libraryList,
|
extensionRegistrars, librariesScope, libraryList,
|
||||||
isCommonSource = { it.isCommonSource == true },
|
isCommonSource = { it.isCommonSource == true },
|
||||||
|
isScript = { it.isScript() },
|
||||||
fileBelongsToModule = { file, moduleName -> file.hmppModuleName == moduleName },
|
fileBelongsToModule = { file, moduleName -> file.hmppModuleName == moduleName },
|
||||||
createProviderAndScopeForIncrementalCompilation = { providerAndScopeForIncrementalCompilation }
|
createProviderAndScopeForIncrementalCompilation = { providerAndScopeForIncrementalCompilation }
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -296,6 +296,7 @@ fun compileModuleToAnalyzedFir(
|
|||||||
allSources, moduleConfiguration, projectEnvironment, Name.special("<$rootModuleName>"),
|
allSources, moduleConfiguration, projectEnvironment, Name.special("<$rootModuleName>"),
|
||||||
extensionRegistrars, librariesScope, libraryList,
|
extensionRegistrars, librariesScope, libraryList,
|
||||||
isCommonSource = input.groupedSources.isCommonSourceForLt,
|
isCommonSource = input.groupedSources.isCommonSourceForLt,
|
||||||
|
isScript = { false },
|
||||||
fileBelongsToModule = input.groupedSources.fileBelongsToModuleForLt,
|
fileBelongsToModule = input.groupedSources.fileBelongsToModuleForLt,
|
||||||
createProviderAndScopeForIncrementalCompilation = { files ->
|
createProviderAndScopeForIncrementalCompilation = { files ->
|
||||||
val scope = projectEnvironment.getSearchScopeBySourceFiles(files)
|
val scope = projectEnvironment.getSearchScopeBySourceFiles(files)
|
||||||
|
|||||||
+1
@@ -82,6 +82,7 @@ class JvmLoadedMetadataDumpHandler(testServices: TestServices) : AbstractLoadedM
|
|||||||
environment.getSearchScopeForProjectLibraries(),
|
environment.getSearchScopeForProjectLibraries(),
|
||||||
libraryList,
|
libraryList,
|
||||||
isCommonSource = { false },
|
isCommonSource = { false },
|
||||||
|
isScript = { false },
|
||||||
fileBelongsToModule = { _, _ -> false },
|
fileBelongsToModule = { _, _ -> false },
|
||||||
createProviderAndScopeForIncrementalCompilation = { null }
|
createProviderAndScopeForIncrementalCompilation = { null }
|
||||||
)
|
)
|
||||||
|
|||||||
+2
-1
@@ -365,7 +365,8 @@ private fun doCompileWithK2(
|
|||||||
)
|
)
|
||||||
val session = prepareJvmSessions(
|
val session = prepareJvmSessions(
|
||||||
sourceFiles, kotlinCompilerConfiguration, projectEnvironment, Name.special("<$rootModuleName>"), extensionRegistrars,
|
sourceFiles, kotlinCompilerConfiguration, projectEnvironment, Name.special("<$rootModuleName>"), extensionRegistrars,
|
||||||
librariesScope, libraryList, isCommonSourceForPsi, fileBelongsToModuleForPsi,
|
librariesScope, libraryList, isCommonSourceForPsi, { false },
|
||||||
|
fileBelongsToModuleForPsi,
|
||||||
createProviderAndScopeForIncrementalCompilation = { files ->
|
createProviderAndScopeForIncrementalCompilation = { files ->
|
||||||
createContextForIncrementalCompilation(
|
createContextForIncrementalCompilation(
|
||||||
compilerInput.configuration,
|
compilerInput.configuration,
|
||||||
|
|||||||
+2
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
package foo
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
println("OK")
|
println("OK")
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
fun main() {
|
||||||
|
println(SimpleScript_main().ok)
|
||||||
|
println(ok)
|
||||||
|
}
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
foo.main()
|
||||||
+53
-3
@@ -13,12 +13,14 @@ import org.jetbrains.kotlin.scripting.compiler.test.linesSplitTrim
|
|||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.net.URLClassLoader
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
|
||||||
class ScriptingWithCliCompilerTest {
|
class ScriptingWithCliCompilerTest {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TEST_DATA_DIR = "plugins/scripting/scripting-compiler/testData"
|
const val TEST_DATA_DIR = "plugins/scripting/scripting-compiler/testData"
|
||||||
|
val SIMPLE_TEST_SCRIPT = "$TEST_DATA_DIR/compiler/mixedCompilation/simpleScript.main.kts"
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -196,7 +198,7 @@ class ScriptingWithCliCompilerTest {
|
|||||||
"$TEST_DATA_DIR/compiler/mixedCompilation/simpleScriptInstance.kt"
|
"$TEST_DATA_DIR/compiler/mixedCompilation/simpleScriptInstance.kt"
|
||||||
else
|
else
|
||||||
"$TEST_DATA_DIR/compiler/mixedCompilation/nonScript.kt",
|
"$TEST_DATA_DIR/compiler/mixedCompilation/nonScript.kt",
|
||||||
"$TEST_DATA_DIR/compiler/mixedCompilation/simpleScript.main.kts"
|
SIMPLE_TEST_SCRIPT
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -240,6 +242,54 @@ class ScriptingWithCliCompilerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAccessRegularSourceFromScript() {
|
||||||
|
withTempDir { tmpdir ->
|
||||||
|
val scriptPath = "$TEST_DATA_DIR/compiler/mixedCompilation/scriptAccessingNonScript.main.kts"
|
||||||
|
val ret =
|
||||||
|
CLITool.doMainNoExit(
|
||||||
|
K2JVMCompiler(),
|
||||||
|
arrayOf(
|
||||||
|
"-P", "plugin:kotlin.scripting:disable-script-definitions-autoloading=true",
|
||||||
|
"-cp", getMainKtsClassPath().joinToString(File.pathSeparator), "-d", tmpdir.path,
|
||||||
|
"-Xuse-fir-lt=false",
|
||||||
|
"-Xallow-any-scripts-in-source-roots", "-verbose",
|
||||||
|
"$TEST_DATA_DIR/compiler/mixedCompilation/nonScript.kt",
|
||||||
|
scriptPath,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Assert.assertEquals(ExitCode.OK.code, ret.code)
|
||||||
|
val (out, _, _) = captureOutErrRet {
|
||||||
|
val cl = URLClassLoader((getMainKtsClassPath() + tmpdir).map { it.toURI().toURL() }.toTypedArray())
|
||||||
|
val klass = cl.loadClass("ScriptAccessingNonScript_main")
|
||||||
|
val ctor = klass.constructors.single()
|
||||||
|
ctor.newInstance(arrayOf<String>(), File(scriptPath))
|
||||||
|
}
|
||||||
|
Assert.assertEquals("OK", out.trim())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAccessScriptFromRegularSource() {
|
||||||
|
withTempDir { tmpdir ->
|
||||||
|
val (_, err, ret) = captureOutErrRet {
|
||||||
|
CLITool.doMainNoExit(
|
||||||
|
K2JVMCompiler(),
|
||||||
|
arrayOf(
|
||||||
|
"-P", "plugin:kotlin.scripting:disable-script-definitions-autoloading=true",
|
||||||
|
"-cp", getMainKtsClassPath().joinToString(File.pathSeparator), "-d", tmpdir.path,
|
||||||
|
"-Xuse-fir-lt=false",
|
||||||
|
"-Xallow-any-scripts-in-source-roots", "-verbose",
|
||||||
|
"$TEST_DATA_DIR/compiler/mixedCompilation/nonScriptAccessingScript.kt",
|
||||||
|
SIMPLE_TEST_SCRIPT
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
println(err)
|
||||||
|
Assert.assertEquals(ExitCode.COMPILATION_ERROR.code, ret.code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testScriptMainKtsDiscovery() {
|
fun testScriptMainKtsDiscovery() {
|
||||||
withTempDir { tmpdir ->
|
withTempDir { tmpdir ->
|
||||||
@@ -256,7 +306,7 @@ class ScriptingWithCliCompilerTest {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Assert.assertEquals(0, ret.code)
|
Assert.assertEquals(ExitCode.OK.code, ret.code)
|
||||||
return err.linesSplitTrim()
|
return err.linesSplitTrim()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +315,7 @@ class ScriptingWithCliCompilerTest {
|
|||||||
val res1 = compileSuccessfullyGetStdErr("$TEST_DATA_DIR/compiler/mixedCompilation/nonScript.kt")
|
val res1 = compileSuccessfullyGetStdErr("$TEST_DATA_DIR/compiler/mixedCompilation/nonScript.kt")
|
||||||
Assert.assertTrue(res1.none { it.startsWith(loadMainKtsMessage) })
|
Assert.assertTrue(res1.none { it.startsWith(loadMainKtsMessage) })
|
||||||
|
|
||||||
val res2 = compileSuccessfullyGetStdErr("$TEST_DATA_DIR/compiler/mixedCompilation/simpleScript.main.kts")
|
val res2 = compileSuccessfullyGetStdErr(SIMPLE_TEST_SCRIPT)
|
||||||
Assert.assertTrue(res2.any { it.startsWith(loadMainKtsMessage) })
|
Assert.assertTrue(res2.any { it.startsWith(loadMainKtsMessage) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user