[CLI] add support running scripts in js compiler, extract common code with jvm part

This commit is contained in:
Vitaliy.Tikhonov
2019-09-02 21:04:08 +03:00
committed by romanart
parent 50c08b25d3
commit f59e393e37
18 changed files with 175 additions and 122 deletions
@@ -76,6 +76,9 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
) )
var progressiveMode by FreezableVar(false) var progressiveMode by FreezableVar(false)
@Argument(value = "-script", description = "Evaluate the script file")
var script: Boolean by FreezableVar(false)
@Argument(value = "-P", valueDescription = PLUGIN_OPTION_FORMAT, description = "Pass an option to a plugin") @Argument(value = "-P", valueDescription = PLUGIN_OPTION_FORMAT, description = "Pass an option to a plugin")
var pluginOptions: Array<String>? by FreezableVar(null) var pluginOptions: Array<String>? by FreezableVar(null)
@@ -304,6 +307,9 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
) )
var useFir: Boolean by FreezableVar(false) var useFir: Boolean by FreezableVar(false)
@Argument(value = "-Xdisable-default-scripting-plugin", description = "Do not enable scripting plugin by default")
var disableDefaultScriptingPlugin: Boolean by FreezableVar(false)
open fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> { open fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> {
return HashMap<AnalysisFlag<*>, Any>().apply { return HashMap<AnalysisFlag<*>, Any>().apply {
put(AnalysisFlags.skipMetadataVersionCheck, skipMetadataVersionCheck) put(AnalysisFlags.skipMetadataVersionCheck, skipMetadataVersionCheck)
@@ -137,4 +137,7 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
@Argument(value = "-Xmetadata-only", description = "Generate *.meta.js and *.kjsm files only") @Argument(value = "-Xmetadata-only", description = "Generate *.meta.js and *.kjsm files only")
var metadataOnly: Boolean by FreezableVar(false) var metadataOnly: Boolean by FreezableVar(false)
@Argument(value = "-Xenable-js-scripting", description = "Enable experimental support of .kts files using K/JS (with -Xir only)")
var enableJsScripting: Boolean by FreezableVar(false)
} }
@@ -45,9 +45,6 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
@Argument(value = "-no-reflect", description = "Don't include kotlin-reflect.jar into classpath") @Argument(value = "-no-reflect", description = "Don't include kotlin-reflect.jar into classpath")
var noReflect: Boolean by FreezableVar(false) var noReflect: Boolean by FreezableVar(false)
@Argument(value = "-script", description = "Evaluate the script file")
var script: Boolean by FreezableVar(false)
@Argument( @Argument(
value = "-script-templates", value = "-script-templates",
valueDescription = "<fully qualified class name[,]>", valueDescription = "<fully qualified class name[,]>",
@@ -254,9 +251,6 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
) )
var jvmDefault: String by FreezableVar(JvmDefaultMode.DEFAULT.description) var jvmDefault: String by FreezableVar(JvmDefaultMode.DEFAULT.description)
@Argument(value = "-Xdisable-default-scripting-plugin", description = "Do not enable scripting plugin by default")
var disableDefaultScriptingPlugin: Boolean by FreezableVar(false)
@Argument(value = "-Xdisable-standard-script", description = "Disable standard kotlin script support") @Argument(value = "-Xdisable-standard-script", description = "Disable standard kotlin script support")
var disableStandardScript: Boolean by FreezableVar(false) var disableStandardScript: Boolean by FreezableVar(false)
@@ -95,6 +95,9 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
return irCompiler; return irCompiler;
} }
@Override
protected void addPlatformOptions(@NotNull List<String> $self, @NotNull K2JSCompilerArguments arguments) {}
static { static {
moduleKindMap.put(K2JsArgumentConstants.MODULE_PLAIN, ModuleKind.PLAIN); moduleKindMap.put(K2JsArgumentConstants.MODULE_PLAIN, ModuleKind.PLAIN);
moduleKindMap.put(K2JsArgumentConstants.MODULE_COMMONJS, ModuleKind.COMMON_JS); moduleKindMap.put(K2JsArgumentConstants.MODULE_COMMONJS, ModuleKind.COMMON_JS);
@@ -195,8 +198,7 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
return COMPILATION_ERROR; return COMPILATION_ERROR;
} }
ExitCode pluginLoadResult = ExitCode pluginLoadResult = loadPlugins(paths, arguments, configuration);
PluginCliParser.loadPluginsSafe(arguments.getPluginClasspaths(), arguments.getPluginOptions(), configuration);
if (pluginLoadResult != ExitCode.OK) return pluginLoadResult; if (pluginLoadResult != ExitCode.OK) return pluginLoadResult;
configuration.put(JSConfigurationKeys.LIBRARIES, configureLibraries(arguments, paths, messageCollector)); configuration.put(JSConfigurationKeys.LIBRARIES, configureLibraries(arguments, paths, messageCollector));
@@ -9,11 +9,11 @@ import com.intellij.openapi.Disposable
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.cli.common.* import org.jetbrains.kotlin.cli.common.*
import org.jetbrains.kotlin.cli.common.ExitCode.COMPILATION_ERROR import org.jetbrains.kotlin.cli.common.ExitCode.*
import org.jetbrains.kotlin.cli.common.ExitCode.OK
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot
import org.jetbrains.kotlin.cli.common.extensions.ScriptEvaluationExtension
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
@@ -43,6 +43,7 @@ import org.jetbrains.kotlin.serialization.js.ModuleKind
import org.jetbrains.kotlin.util.Logger import org.jetbrains.kotlin.util.Logger
import org.jetbrains.kotlin.utils.JsMetadataVersion import org.jetbrains.kotlin.utils.JsMetadataVersion
import org.jetbrains.kotlin.utils.KotlinPaths import org.jetbrains.kotlin.utils.KotlinPaths
import org.jetbrains.kotlin.utils.PathUtil
import org.jetbrains.kotlin.utils.join import org.jetbrains.kotlin.utils.join
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
@@ -70,6 +71,33 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
): ExitCode { ): ExitCode {
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
val pluginLoadResult = loadPlugins(paths, arguments, configuration)
if (pluginLoadResult != ExitCode.OK) return pluginLoadResult
//TODO: add to configuration everything that may come in handy at script compiler and use it there
if (arguments.script) {
if (!arguments.enableJsScripting) {
messageCollector.report(ERROR, "Script for K/JS should be enabled explicitly, see -Xenable-js-scripting")
return COMPILATION_ERROR
}
configuration.put(CommonConfigurationKeys.MODULE_NAME, "repl.kts")
val environment = KotlinCoreEnvironment.getOrCreateApplicationEnvironmentForProduction(rootDisposable, configuration)
val projectEnv = KotlinCoreEnvironment.ProjectEnvironment(rootDisposable, environment)
projectEnv.registerExtensionsFromPlugins(configuration)
val scriptingEvaluators = ScriptEvaluationExtension.getInstances(projectEnv.project)
val scriptingEvaluator = scriptingEvaluators.find { it.isAccepted(arguments) }
if (scriptingEvaluator == null) {
messageCollector.report(ERROR, "Unable to evaluate script, no scripting plugin loaded")
return COMPILATION_ERROR
}
return scriptingEvaluator.eval(arguments, configuration, projectEnv)
}
if (arguments.freeArgs.isEmpty() && !IncrementalCompilation.isEnabledForJs()) { if (arguments.freeArgs.isEmpty() && !IncrementalCompilation.isEnabledForJs()) {
if (arguments.version) { if (arguments.version) {
return OK return OK
@@ -78,13 +106,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
return COMPILATION_ERROR return COMPILATION_ERROR
} }
val pluginLoadResult = PluginCliParser.loadPluginsSafe(
arguments.pluginClasspaths,
arguments.pluginOptions,
configuration
)
if (pluginLoadResult != OK) return pluginLoadResult
val libraries: List<String> = configureLibraries(arguments.libraries) val libraries: List<String> = configureLibraries(arguments.libraries)
val friendLibraries: List<String> = configureLibraries(arguments.friendModules) val friendLibraries: List<String> = configureLibraries(arguments.friendModules)
@@ -99,11 +120,11 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val environmentForJS = val environmentForJS =
KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JS_CONFIG_FILES) KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JS_CONFIG_FILES)
val projectJs = environmentForJS.project
val project = environmentForJS.project val configurationJs = environmentForJS.configuration
val sourcesFiles = environmentForJS.getSourceFiles() val sourcesFiles = environmentForJS.getSourceFiles()
environmentForJS.configuration.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage) configurationJs.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage)
if (!checkKotlinPackageUsage(environmentForJS, sourcesFiles)) return ExitCode.COMPILATION_ERROR if (!checkKotlinPackageUsage(environmentForJS, sourcesFiles)) return ExitCode.COMPILATION_ERROR
@@ -128,9 +149,11 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val outputFile = File(outputFilePath) val outputFile = File(outputFilePath)
configuration.put(CommonConfigurationKeys.MODULE_NAME, FileUtil.getNameWithoutExtension(outputFile)) configurationJs.put(CommonConfigurationKeys.MODULE_NAME, FileUtil.getNameWithoutExtension(outputFile))
val config = JsConfig(project, configuration) // TODO: in this method at least 3 different compiler configurations are used (original, env.configuration, jsConfig.configuration)
// Such situation seems a bit buggy...
val config = JsConfig(projectJs, configurationJs)
val outputDir: File = outputFile.parentFile ?: outputFile.absoluteFile.parentFile!! val outputDir: File = outputFile.parentFile ?: outputFile.absoluteFile.parentFile!!
try { try {
config.configuration.put(JSConfigurationKeys.OUTPUT_DIR, outputDir.canonicalFile) config.configuration.put(JSConfigurationKeys.OUTPUT_DIR, outputDir.canonicalFile)
@@ -179,9 +202,9 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val phaseConfig = createPhaseConfig(jsPhases, arguments, messageCollector) val phaseConfig = createPhaseConfig(jsPhases, arguments, messageCollector)
val compiledModule = compile( val compiledModule = compile(
project, projectJs,
sourcesFiles, sourcesFiles,
configuration, config.configuration,
phaseConfig, phaseConfig,
allDependencies = resolvedLibraries, allDependencies = resolvedLibraries,
friendDependencies = friendDependencies, friendDependencies = friendDependencies,
@@ -293,6 +316,8 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
return JsMetadataVersion(*versionArray) return JsMetadataVersion(*versionArray)
} }
override fun MutableList<String>.addPlatformOptions(arguments: K2JSCompilerArguments) {}
companion object { companion object {
private val moduleKindMap = mapOf( private val moduleKindMap = mapOf(
K2JsArgumentConstants.MODULE_PLAIN to ModuleKind.PLAIN, K2JsArgumentConstants.MODULE_PLAIN to ModuleKind.PLAIN,
@@ -349,4 +374,15 @@ fun messageCollectorLogger(collector: MessageCollector) = object : Logger {
(collector as? GroupingMessageCollector)?.flush() (collector as? GroupingMessageCollector)?.flush()
kotlin.error(message) kotlin.error(message)
} }
}
fun loadPluginsForTests(configuration: CompilerConfiguration): ExitCode {
var pluginClasspaths: Iterable<String> = emptyList()
val kotlinPaths = PathUtil.kotlinPathsForCompiler
val libPath = kotlinPaths.libPath.takeIf { it.exists() && it.isDirectory } ?: File(".")
val (jars, _) =
PathUtil.KOTLIN_SCRIPTING_PLUGIN_CLASSPATH_JARS.mapNotNull { File(libPath, it) }.partition { it.exists() }
pluginClasspaths = jars.map { it.canonicalPath } + pluginClasspaths
return PluginCliParser.loadPluginsSafe(pluginClasspaths, mutableListOf(), configuration)
} }
@@ -24,11 +24,10 @@ import org.jetbrains.kotlin.cli.common.ExitCode.COMPILATION_ERROR
import org.jetbrains.kotlin.cli.common.ExitCode.INTERNAL_ERROR import org.jetbrains.kotlin.cli.common.ExitCode.INTERNAL_ERROR
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback
import org.jetbrains.kotlin.cli.common.messages.*
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO
import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
@@ -36,8 +35,10 @@ import org.jetbrains.kotlin.progress.CompilationCanceledException
import org.jetbrains.kotlin.progress.CompilationCanceledStatus import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.utils.KotlinPaths import org.jetbrains.kotlin.utils.KotlinPaths
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File import java.io.File
import java.io.PrintStream import java.io.PrintStream
import java.util.ArrayList
abstract class CLICompiler<A : CommonCompilerArguments> : CLITool<A>() { abstract class CLICompiler<A : CommonCompilerArguments> : CLITool<A>() {
@@ -134,5 +135,51 @@ abstract class CLICompiler<A : CommonCompilerArguments> : CLITool<A>() {
rootDisposable: Disposable, rootDisposable: Disposable,
paths: KotlinPaths? paths: KotlinPaths?
): ExitCode ): ExitCode
protected abstract fun MutableList<String>.addPlatformOptions(arguments: A)
protected fun loadPlugins(paths: KotlinPaths?, arguments: A, configuration: CompilerConfiguration): ExitCode {
var pluginClasspaths: Iterable<String> = arguments.pluginClasspaths?.asIterable() ?: emptyList()
val pluginOptions = arguments.pluginOptions?.toMutableList() ?: ArrayList()
if (!arguments.disableDefaultScriptingPlugin) {
val explicitOrLoadedScriptingPlugin =
pluginClasspaths.any { File(it).name.startsWith(PathUtil.KOTLIN_SCRIPTING_COMPILER_PLUGIN_NAME) } ||
tryLoadScriptingPluginFromCurrentClassLoader(configuration)
if (!explicitOrLoadedScriptingPlugin) {
val kotlinPaths = paths ?: PathUtil.kotlinPathsForCompiler
val libPath = kotlinPaths.libPath.takeIf { it.exists() && it.isDirectory } ?: File(".")
val (jars, missingJars) =
PathUtil.KOTLIN_SCRIPTING_PLUGIN_CLASSPATH_JARS.map { File(libPath, it) }.partition { it.exists() }
if (missingJars.isEmpty()) {
pluginClasspaths = jars.map { it.canonicalPath } + pluginClasspaths
} else {
val messageCollector = configuration.getNotNull(MESSAGE_COLLECTOR_KEY)
messageCollector.report(
CompilerMessageSeverity.LOGGING,
"Scripting plugin will not be loaded: not all required jars are present in the classpath (missing files: $missingJars)"
)
}
}
pluginOptions.addPlatformOptions(arguments)
} else {
pluginOptions.add("plugin:kotlin.scripting:disable=true")
}
return PluginCliParser.loadPluginsSafe(pluginClasspaths, pluginOptions, configuration)
}
private fun tryLoadScriptingPluginFromCurrentClassLoader(configuration: CompilerConfiguration): Boolean = try {
val pluginRegistrarClass = PluginCliParser::class.java.classLoader.loadClass(
"org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar"
)
val pluginRegistrar = pluginRegistrarClass.newInstance() as? ComponentRegistrar
if (pluginRegistrar != null) {
configuration.add(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS, pluginRegistrar)
true
} else false
} catch (_: Throwable) {
// TODO: add finer error processing and logging
false
}
} }
@@ -198,59 +198,17 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
} }
} }
private fun loadPlugins(paths: KotlinPaths?, arguments: K2JVMCompilerArguments, configuration: CompilerConfiguration): ExitCode { override fun MutableList<String>.addPlatformOptions(arguments: K2JVMCompilerArguments) {
var pluginClasspaths: Iterable<String> = arguments.pluginClasspaths?.asIterable() ?: emptyList() if (arguments.scriptTemplates?.isNotEmpty() == true) {
val pluginOptions = arguments.pluginOptions?.toMutableList() ?: ArrayList() add("plugin:kotlin.scripting:script-templates=${arguments.scriptTemplates!!.joinToString(",")}")
}
if (!arguments.disableDefaultScriptingPlugin) { if (arguments.scriptResolverEnvironment?.isNotEmpty() == true) {
val explicitOrLoadedScriptingPlugin = add(
pluginClasspaths.any { File(it).name.startsWith(PathUtil.KOTLIN_SCRIPTING_COMPILER_PLUGIN_NAME) } || "plugin:kotlin.scripting:script-resolver-environment=${arguments.scriptResolverEnvironment!!.joinToString(
tryLoadScriptingPluginFromCurrentClassLoader(configuration) ","
// if scripting plugin is not enabled explicitly (probably from another path) and not in the classpath already, )}"
// try to find and enable it implicitly )
if (!explicitOrLoadedScriptingPlugin) {
val kotlinPaths = paths ?: PathUtil.kotlinPathsForCompiler
val libPath = kotlinPaths.libPath.takeIf { it.exists() && it.isDirectory } ?: File(".")
val (jars, missingJars) =
PathUtil.KOTLIN_SCRIPTING_PLUGIN_CLASSPATH_JARS.mapNotNull { File(libPath, it) }.partition { it.exists() }
if (missingJars.isEmpty()) {
pluginClasspaths = jars.map { it.canonicalPath } + pluginClasspaths
} else {
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
messageCollector.report(
LOGGING,
"Scripting plugin will not be loaded: not all required jars are present in the classpath (missing files: $missingJars)"
)
}
}
if (arguments.scriptTemplates?.isNotEmpty() == true) {
pluginOptions.add("plugin:kotlin.scripting:script-templates=${arguments.scriptTemplates!!.joinToString(",")}")
}
if (arguments.scriptResolverEnvironment?.isNotEmpty() == true) {
pluginOptions.add(
"plugin:kotlin.scripting:script-resolver-environment=${arguments.scriptResolverEnvironment!!.joinToString(
","
)}"
)
}
} else {
pluginOptions.add("plugin:kotlin.scripting:disable=true")
} }
return PluginCliParser.loadPluginsSafe(pluginClasspaths, pluginOptions, configuration)
}
private fun tryLoadScriptingPluginFromCurrentClassLoader(configuration: CompilerConfiguration): Boolean = try {
val pluginRegistrarClass = PluginCliParser::class.java.classLoader.loadClass(
"org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar"
)
val pluginRegistrar = pluginRegistrarClass.newInstance() as? ComponentRegistrar
if (pluginRegistrar != null) {
configuration.add(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS, pluginRegistrar)
true
} else false
} catch (_: Throwable) {
// TODO: add finer error processing and logging
false
} }
private fun createCoreEnvironment( private fun createCoreEnvironment(
@@ -49,6 +49,8 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
// No specific arguments yet // No specific arguments yet
} }
override fun MutableList<String>.addPlatformOptions(arguments: K2MetadataCompilerArguments) {}
override fun doExecute( override fun doExecute(
arguments: K2MetadataCompilerArguments, arguments: K2MetadataCompilerArguments,
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
@@ -57,7 +59,7 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
): ExitCode { ): ExitCode {
val collector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) val collector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
val pluginLoadResult = PluginCliParser.loadPluginsSafe(arguments.pluginClasspaths, arguments.pluginOptions, configuration) val pluginLoadResult = loadPlugins(paths, arguments, configuration)
if (pluginLoadResult != ExitCode.OK) return pluginLoadResult if (pluginLoadResult != ExitCode.OK) return pluginLoadResult
for (arg in arguments.freeArgs) { for (arg in arguments.freeArgs) {
+3
View File
@@ -1,5 +1,6 @@
Usage: kotlinc-js <options> <source files> Usage: kotlinc-js <options> <source files>
where advanced options include: where advanced options include:
-Xenable-js-scripting Enable experimental support of .kts files using K/JS (with -Xir only)
-Xfriend-modules=<path> Paths to friend modules -Xfriend-modules=<path> Paths to friend modules
-Xfriend-modules-disabled Disable internal declaration export -Xfriend-modules-disabled Disable internal declaration export
-Xir Use IR backend -Xir Use IR backend
@@ -17,6 +18,8 @@ where advanced options include:
Should be a subset of sources passed as free arguments Should be a subset of sources passed as free arguments
-Xcoroutines={enable|warn|error} -Xcoroutines={enable|warn|error}
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
-Xdisable-default-scripting-plugin
Do not enable scripting plugin by default
-Xdisable-phases Disable backend phases -Xdisable-phases Disable backend phases
-Xdump-directory Dump backend state into directory -Xdump-directory Dump backend state into directory
-Xdump-fqname FqName of declaration that should be dumped -Xdump-fqname FqName of declaration that should be dumped
+1
View File
@@ -28,6 +28,7 @@ where possible options include:
instead of going through a graceful migration cycle. instead of going through a graceful migration cycle.
Code written in the progressive mode is backward compatible; however, code written in Code written in the progressive mode is backward compatible; however, code written in
non-progressive mode may cause compilation errors in the progressive mode. non-progressive mode may cause compilation errors in the progressive mode.
-script Evaluate the script file
-nowarn Generate no warnings -nowarn Generate no warnings
-verbose Enable verbose logging output -verbose Enable verbose logging output
-version Display compiler version -version Display compiler version
+2 -2
View File
@@ -17,8 +17,6 @@ where advanced options include:
default is 'disable' in language version 1.2 and below, default is 'disable' in language version 1.2 and below,
'enable' since language version 1.3 'enable' since language version 1.3
-Xdump-declarations-to=<path> Path to JSON file to dump Java to Kotlin declaration mappings -Xdump-declarations-to=<path> Path to JSON file to dump Java to Kotlin declaration mappings
-Xdisable-default-scripting-plugin
Do not enable scripting plugin by default
-Xdisable-standard-script Disable standard kotlin script support -Xdisable-standard-script Disable standard kotlin script support
-Xfriend-paths=<path> Paths to output directories for friend modules (whose internals should be visible) -Xfriend-paths=<path> Paths to output directories for friend modules (whose internals should be visible)
-Xmultifile-parts-inherit Compile multifile classes as a hierarchy of parts and facade -Xmultifile-parts-inherit Compile multifile classes as a hierarchy of parts and facade
@@ -79,6 +77,8 @@ where advanced options include:
Should be a subset of sources passed as free arguments Should be a subset of sources passed as free arguments
-Xcoroutines={enable|warn|error} -Xcoroutines={enable|warn|error}
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
-Xdisable-default-scripting-plugin
Do not enable scripting plugin by default
-Xdisable-phases Disable backend phases -Xdisable-phases Disable backend phases
-Xdump-directory Dump backend state into directory -Xdump-directory Dump backend state into directory
-Xdump-fqname FqName of declaration that should be dumped -Xdump-fqname FqName of declaration that should be dumped
+1 -1
View File
@@ -10,7 +10,6 @@ where possible options include:
-no-jdk Don't include Java runtime into classpath -no-jdk Don't include Java runtime into classpath
-no-reflect Don't include kotlin-reflect.jar into classpath -no-reflect Don't include kotlin-reflect.jar into classpath
-no-stdlib Don't include kotlin-stdlib.jar or kotlin-reflect.jar into classpath -no-stdlib Don't include kotlin-stdlib.jar or kotlin-reflect.jar into classpath
-script Evaluate the script file
-script-templates <fully qualified class name[,]> -script-templates <fully qualified class name[,]>
Script definition template classes Script definition template classes
-Werror Report an error if there are any warnings -Werror Report an error if there are any warnings
@@ -26,6 +25,7 @@ where possible options include:
instead of going through a graceful migration cycle. instead of going through a graceful migration cycle.
Code written in the progressive mode is backward compatible; however, code written in Code written in the progressive mode is backward compatible; however, code written in
non-progressive mode may cause compilation errors in the progressive mode. non-progressive mode may cause compilation errors in the progressive mode.
-script Evaluate the script file
-nowarn Generate no warnings -nowarn Generate no warnings
-verbose Enable verbose logging output -verbose Enable verbose logging output
-version Display compiler version -version Display compiler version
@@ -66,6 +66,8 @@ object PathUtil {
const val KOTLIN_SCRIPTING_COMMON_JAR = "$KOTLIN_SCRIPTING_COMMON_NAME.jar" const val KOTLIN_SCRIPTING_COMMON_JAR = "$KOTLIN_SCRIPTING_COMMON_NAME.jar"
const val KOTLIN_SCRIPTING_JVM_NAME = "kotlin-scripting-jvm" const val KOTLIN_SCRIPTING_JVM_NAME = "kotlin-scripting-jvm"
const val KOTLIN_SCRIPTING_JVM_JAR = "$KOTLIN_SCRIPTING_JVM_NAME.jar" const val KOTLIN_SCRIPTING_JVM_JAR = "$KOTLIN_SCRIPTING_JVM_NAME.jar"
const val KOTLIN_SCRIPTING_JS_NAME = "kotlin-scripting-js"
const val KOTLIN_SCRIPTING_JS_JAR = "$KOTLIN_SCRIPTING_JS_NAME.jar"
const val KOTLIN_DAEMON_NAME = "kotlin-daemon" const val KOTLIN_DAEMON_NAME = "kotlin-daemon"
const val KTOR_NAME = "ktor-network-1.0.1" const val KTOR_NAME = "ktor-network-1.0.1"
const val KOTLIN_DAEMON_JAR = "$KOTLIN_SCRIPTING_JVM_NAME.jar" const val KOTLIN_DAEMON_JAR = "$KOTLIN_SCRIPTING_JVM_NAME.jar"
@@ -75,10 +77,12 @@ object PathUtil {
const val KOTLINX_COROUTINES_CORE_JAR = "$KOTLINX_COROUTINES_CORE_NAME.jar" const val KOTLINX_COROUTINES_CORE_JAR = "$KOTLINX_COROUTINES_CORE_NAME.jar"
const val KOTLIN_SCRIPTING_COMPILER_IMPL_NAME = "kotlin-scripting-compiler-impl" const val KOTLIN_SCRIPTING_COMPILER_IMPL_NAME = "kotlin-scripting-compiler-impl"
const val KOTLIN_SCRIPTING_COMPILER_IMPL_JAR = "$KOTLIN_SCRIPTING_COMPILER_IMPL_NAME.jar" const val KOTLIN_SCRIPTING_COMPILER_IMPL_JAR = "$KOTLIN_SCRIPTING_COMPILER_IMPL_NAME.jar"
const val JS_ENGINES_NAME = "js.engines"
const val JS_ENGINES_JAR = "$JS_ENGINES_NAME.jar"
val KOTLIN_SCRIPTING_PLUGIN_CLASSPATH_JARS = arrayOf( val KOTLIN_SCRIPTING_PLUGIN_CLASSPATH_JARS = arrayOf(
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMPILER_IMPL_JAR, KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMPILER_IMPL_JAR,
KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR, KOTLIN_SCRIPTING_JS_JAR, JS_ENGINES_JAR
) )
const val KOTLIN_TEST_NAME = "kotlin-test" const val KOTLIN_TEST_NAME = "kotlin-test"
@@ -23,8 +23,6 @@ import kotlin.script.experimental.host.toScriptSource
abstract class AbstractScriptEvaluationExtension : ScriptEvaluationExtension { abstract class AbstractScriptEvaluationExtension : ScriptEvaluationExtension {
abstract fun getSourcePath(arguments: CommonCompilerArguments): String
abstract fun setupScriptConfiguration(configuration: CompilerConfiguration, sourcePath: String) abstract fun setupScriptConfiguration(configuration: CompilerConfiguration, sourcePath: String)
abstract fun createEnvironment( abstract fun createEnvironment(
@@ -40,11 +38,7 @@ abstract class AbstractScriptEvaluationExtension : ScriptEvaluationExtension {
scriptCompilationConfiguration: ScriptCompilationConfiguration scriptCompilationConfiguration: ScriptCompilationConfiguration
): ResultWithDiagnostics<CompiledScript<*>> ): ResultWithDiagnostics<CompiledScript<*>>
abstract suspend fun preprocessEvaluation( protected abstract fun ScriptEvaluationConfiguration.Builder.platformEvaluationConfiguration()
scriptEvaluator: ScriptEvaluator,
scriptCompilationConfiguration: ScriptCompilationConfiguration,
evaluationConfiguration: ScriptEvaluationConfiguration
)
override fun eval( override fun eval(
arguments: CommonCompilerArguments, arguments: CommonCompilerArguments,
@@ -57,12 +51,14 @@ abstract class AbstractScriptEvaluationExtension : ScriptEvaluationExtension {
messageCollector.report(CompilerMessageSeverity.ERROR, "Unable to process the script, scripting plugin is not configured") messageCollector.report(CompilerMessageSeverity.ERROR, "Unable to process the script, scripting plugin is not configured")
return ExitCode.COMPILATION_ERROR return ExitCode.COMPILATION_ERROR
} }
val sourcePath = getSourcePath(arguments) val sourcePath = arguments.freeArgs.first()
setupScriptConfiguration(configuration, sourcePath) setupScriptConfiguration(configuration, sourcePath)
val environment = createEnvironment(projectEnvironment, configuration) val environment = createEnvironment(projectEnvironment, configuration)
if (messageCollector.hasErrors()) return ExitCode.COMPILATION_ERROR
val scriptFile = File(sourcePath) val scriptFile = File(sourcePath)
if (scriptFile.isDirectory || !scriptDefinitionProvider.isScript(scriptFile)) { if (scriptFile.isDirectory || !scriptDefinitionProvider.isScript(scriptFile)) {
val extensionHint = val extensionHint =
@@ -82,6 +78,8 @@ abstract class AbstractScriptEvaluationExtension : ScriptEvaluationExtension {
val evaluationConfiguration = definition.evaluationConfiguration.with { val evaluationConfiguration = definition.evaluationConfiguration.with {
constructorArgs(scriptArgs.toTypedArray()) constructorArgs(scriptArgs.toTypedArray())
platformEvaluationConfiguration()
} }
val scriptCompilationConfiguration = definition.compilationConfiguration val scriptCompilationConfiguration = definition.compilationConfiguration
@@ -99,7 +97,6 @@ abstract class AbstractScriptEvaluationExtension : ScriptEvaluationExtension {
return@runBlocking ExitCode.COMPILATION_ERROR return@runBlocking ExitCode.COMPILATION_ERROR
} }
preprocessEvaluation(scriptEvaluator, scriptCompilationConfiguration, evaluationConfiguration)
val evalResult = scriptEvaluator.invoke(compiledScript, evaluationConfiguration).valueOr { val evalResult = scriptEvaluator.invoke(compiledScript, evaluationConfiguration).valueOr {
for (report in it.reports) { for (report in it.reports) {
messageCollector.report(report.severity.toCompilerMessageSeverity(), report.render(withSeverity = false)) messageCollector.report(report.severity.toCompilerMessageSeverity(), report.render(withSeverity = false))
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.platform import org.jetbrains.kotlin.scripting.definitions.platform
import org.jetbrains.kotlin.scripting.repl.js.CompiledToJsScript import org.jetbrains.kotlin.scripting.repl.js.CompiledToJsScript
import org.jetbrains.kotlin.scripting.repl.js.JsScriptCompiler import org.jetbrains.kotlin.scripting.repl.js.JsScriptCompiler
import org.jetbrains.kotlin.scripting.repl.js.JsScriptDependencyCompiler
import org.jetbrains.kotlin.scripting.repl.js.JsScriptEvaluator import org.jetbrains.kotlin.scripting.repl.js.JsScriptEvaluator
import kotlin.script.experimental.api.* import kotlin.script.experimental.api.*
import kotlin.script.experimental.host.ScriptingHostConfiguration import kotlin.script.experimental.host.ScriptingHostConfiguration
@@ -35,10 +36,6 @@ fun loadScriptConfiguration(configuration: CompilerConfiguration) {
class JsScriptEvaluationExtension : AbstractScriptEvaluationExtension() { class JsScriptEvaluationExtension : AbstractScriptEvaluationExtension() {
override fun getSourcePath(arguments: CommonCompilerArguments): String {
return (arguments as K2JSCompilerArguments).scriptPath!!
}
override fun setupScriptConfiguration(configuration: CompilerConfiguration, sourcePath: String) { override fun setupScriptConfiguration(configuration: CompilerConfiguration, sourcePath: String) {
loadScriptConfiguration(configuration) loadScriptConfiguration(configuration)
} }
@@ -59,8 +56,12 @@ class JsScriptEvaluationExtension : AbstractScriptEvaluationExtension() {
} }
private var environment: KotlinCoreEnvironment? = null private var environment: KotlinCoreEnvironment? = null
private var dependencyJsCode: String? = null
private val scriptCompiler: JsScriptCompiler by lazy { private val scriptCompiler: JsScriptCompiler by lazy {
JsScriptCompiler(environment!!) val env = environment ?: error("Expected environment is initialized prior to compiler instantiation")
JsScriptCompiler(env).apply {
dependencyJsCode = JsScriptDependencyCompiler(env.configuration, nameTables, symbolTable).compile(dependencies)
}
} }
override suspend fun compilerInvoke( override suspend fun compilerInvoke(
@@ -68,22 +69,22 @@ class JsScriptEvaluationExtension : AbstractScriptEvaluationExtension() {
script: SourceCode, script: SourceCode,
scriptCompilationConfiguration: ScriptCompilationConfiguration scriptCompilationConfiguration: ScriptCompilationConfiguration
): ResultWithDiagnostics<CompiledScript<*>> { ): ResultWithDiagnostics<CompiledScript<*>> {
this.environment = environment this.environment = environment
return scriptCompiler.invoke(script, scriptCompilationConfiguration)
return scriptCompiler.invoke(script, scriptCompilationConfiguration).onSuccess {
val compiledResult = it as CompiledToJsScript
val actualResult = dependencyJsCode?.let { d ->
dependencyJsCode = null
CompiledToJsScript(d + "\n" + compiledResult.jsCode, compiledResult.compilationConfiguration)
} ?: compiledResult
ResultWithDiagnostics.Success(actualResult)
}
} }
override suspend fun preprocessEvaluation( override fun ScriptEvaluationConfiguration.Builder.platformEvaluationConfiguration() {
scriptEvaluator: ScriptEvaluator,
scriptCompilationConfiguration: ScriptCompilationConfiguration,
evaluationConfiguration: ScriptEvaluationConfiguration
) {
scriptEvaluator.invoke(
CompiledToJsScript(
scriptCompiler.scriptDependencyBinary,
scriptCompilationConfiguration
),
evaluationConfiguration
)
} }
override fun isAccepted(arguments: CommonCompilerArguments): Boolean { override fun isAccepted(arguments: CommonCompilerArguments): Boolean {
@@ -16,11 +16,15 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ScriptJvmCompilerFromEnvironment import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ScriptJvmCompilerFromEnvironment
import kotlin.script.experimental.api.* import kotlin.script.experimental.api.*
import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator
import kotlin.script.experimental.jvm.baseClassLoader
import kotlin.script.experimental.jvm.jvm
class JvmCliScriptEvaluationExtension : AbstractScriptEvaluationExtension() { class JvmCliScriptEvaluationExtension : AbstractScriptEvaluationExtension() {
override fun getSourcePath(arguments: CommonCompilerArguments): String { override fun ScriptEvaluationConfiguration.Builder.platformEvaluationConfiguration() {
return arguments.freeArgs.first() jvm {
baseClassLoader(null)
}
} }
override fun setupScriptConfiguration(configuration: CompilerConfiguration, sourcePath: String) { override fun setupScriptConfiguration(configuration: CompilerConfiguration, sourcePath: String) {
@@ -53,14 +57,6 @@ class JvmCliScriptEvaluationExtension : AbstractScriptEvaluationExtension() {
return scriptCompiler.compile(script, scriptCompilationConfiguration) return scriptCompiler.compile(script, scriptCompilationConfiguration)
} }
override suspend fun preprocessEvaluation(
scriptEvaluator: ScriptEvaluator,
scriptCompilationConfiguration: ScriptCompilationConfiguration,
evaluationConfiguration: ScriptEvaluationConfiguration
) {
//do nothing
}
override fun isAccepted(arguments: CommonCompilerArguments): Boolean = override fun isAccepted(arguments: CommonCompilerArguments): Boolean =
arguments is K2JVMCompilerArguments && arguments.script arguments is K2JVMCompilerArguments && arguments.script
} }
@@ -51,6 +51,7 @@ class ScriptingCompilerConfigurationComponentRegistrar : ComponentRegistrar {
) )
) )
ScriptEvaluationExtension.registerExtensionIfRequired(project, JvmCliScriptEvaluationExtension()) ScriptEvaluationExtension.registerExtensionIfRequired(project, JvmCliScriptEvaluationExtension())
ScriptEvaluationExtension.registerExtensionIfRequired(project, JsScriptEvaluationExtension())
ShellExtension.registerExtensionIfRequired(project, JvmCliReplShellExtension()) ShellExtension.registerExtensionIfRequired(project, JvmCliReplShellExtension())
ReplFactoryExtension.registerExtensionIfRequired(project, ReplFactoryExtension.registerExtensionIfRequired(project,
JvmStandardReplFactoryExtension() JvmStandardReplFactoryExtension()
+2
View File
@@ -83,6 +83,8 @@ val distLibraryProjects = listOfNotNull(
":kotlin-scripting-compiler", ":kotlin-scripting-compiler",
":kotlin-scripting-compiler-impl", ":kotlin-scripting-compiler-impl",
":kotlin-scripting-jvm", ":kotlin-scripting-jvm",
":kotlin-scripting-js",
":js:js.engines",
":kotlin-stdlib-js-ir".takeIf { kotlinBuildProperties.jsIrDist }, ":kotlin-stdlib-js-ir".takeIf { kotlinBuildProperties.jsIrDist },
":kotlin-source-sections-compiler-plugin", ":kotlin-source-sections-compiler-plugin",
":kotlin-test:kotlin-test-js", ":kotlin-test:kotlin-test-js",