Process script templates everywhere properly:

- add options to disable scripting plugin and standard script definition
- move standard definition adding logic into appropriate place
- fix logic of scripting plugin loading
- add standard script definition on the environment creation to
  ensure compatibility with all usages
- fix testdata
- some minor fixes
This commit is contained in:
Ilya Chernikov
2018-04-06 11:46:00 +02:00
parent b5da48c566
commit a29411a211
9 changed files with 118 additions and 55 deletions
@@ -234,6 +234,9 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
@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")
var disableStandardScript: Boolean by FreezableVar(false)
// Paths to output directories for friend modules.
var friendPaths: Array<String>? by FreezableVar(null)
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.cli.jvm
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.openapi.Disposable
import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.CLICompiler.getLibraryFromHome
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.CLITool
import org.jetbrains.kotlin.cli.common.ExitCode
@@ -68,6 +69,10 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
if (it != OK) return it
}
if (arguments.disableStandardScript) {
configuration.put(JVMConfigurationKeys.DISABLE_STANDARD_SCRIPT_DEFINITION, true)
}
val pluginLoadResult = loadPlugins(paths, arguments, configuration)
if (pluginLoadResult != ExitCode.OK) return pluginLoadResult
@@ -223,35 +228,40 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
private fun loadPlugins(paths: KotlinPaths?, arguments: K2JVMCompilerArguments, configuration: CompilerConfiguration): ExitCode {
val pluginClasspaths = arguments.pluginClasspaths?.toMutableList() ?: ArrayList()
val pluginOptions = arguments.pluginOptions?.toMutableList() ?: ArrayList()
val isEmbeddable =
try {
this::class.java.classLoader.loadClass("com.intellij.mock.MockProject") == null
} catch (_: ClassNotFoundException) {
true
} catch (_: NoClassDefFoundError) {
true
}
if (!isEmbeddable &&
pluginClasspaths.none { File(it).name == PathUtil.KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR } &&
!arguments.disableDefaultScriptingPlugin
) {
// if scripting plugin is not enabled explicitly (probably from another path) try to enable it implicitly
val libPath = paths?.libPath ?: File(".")
val pluginJar = File(libPath, PathUtil.KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR)
val scriptingJar = File(libPath, PathUtil.KOTLIN_SCRIPTING_COMMON_JAR)
val scriptingJvmJar = File(libPath, PathUtil.KOTLIN_SCRIPTING_JVM_JAR)
if (pluginJar.exists() && scriptingJar.exists() && scriptingJvmJar.exists()) {
pluginClasspaths.addAll(listOf(pluginJar.canonicalPath, scriptingJar.canonicalPath, scriptingJvmJar.canonicalPath))
if (arguments.scriptTemplates?.isNotEmpty() == true) {
pluginOptions.add("-P")
pluginOptions.add("plugin:kotlin.scripting:script-templates=${arguments.scriptTemplates!!.joinToString(",")}")
}
if (arguments.scriptResolverEnvironment?.isNotEmpty() == true) {
pluginOptions.add("-P")
pluginOptions.add("plugin:kotlin.scripting:script-resolver-environment=${arguments.scriptResolverEnvironment!!.joinToString(",")}")
if (!arguments.disableDefaultScriptingPlugin) {
val explicitOrLoadedScriptingPlugin =
pluginClasspaths.any { File(it).name == PathUtil.KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR } ||
try {
PluginCliParser::class.java.classLoader.loadClass("org.jetbrains.kotlin.extensions.ScriptingCompilerConfigurationExtension")
true
} catch (_: Throwable) {
false
}
// 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 libPath = paths?.libPath?.takeIf { it.exists() } ?: File(".")
with(PathUtil) {
val jars = arrayOf(KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR)
.mapNotNull { File(libPath, it).takeIf { it.exists() }?.canonicalPath }
if (jars.size == 3) {
pluginClasspaths.addAll(jars)
}
}
}
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)
}
@@ -207,9 +207,6 @@ class KotlinCoreEnvironment private constructor(
})
sourceFiles.sortBy { it.virtualFile.path }
// We should always support at least the standard script definition
configuration.add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, StandardScriptDefinition)
val scriptDefinitionProvider = ScriptDefinitionProvider.getInstance(project) as? CliScriptDefinitionProvider
if (scriptDefinitionProvider != null) {
scriptDefinitionProvider.setScriptDefinitions(
@@ -410,6 +407,12 @@ class KotlinCoreEnvironment private constructor(
parentDisposable: Disposable, configuration: CompilerConfiguration, configFiles: EnvironmentConfigFiles
): KotlinCoreEnvironment {
setCompatibleBuild()
// If not disabled explicitly, we should always support at least the standard script definition
if (!configuration.getBoolean(JVMConfigurationKeys.DISABLE_STANDARD_SCRIPT_DEFINITION) &&
!configuration.getList(JVMConfigurationKeys.SCRIPT_DEFINITIONS).contains(StandardScriptDefinition)
) {
configuration.add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, StandardScriptDefinition)
}
val appEnv = getOrCreateApplicationEnvironmentForProduction(configuration)
// Disposing of the environment is unsafe in production then parallel builds are enabled, but turning it off universally
// breaks a lot of tests, therefore it is disabled for production and enabled for tests
@@ -444,7 +447,10 @@ class KotlinCoreEnvironment private constructor(
parentDisposable: Disposable, initialConfiguration: CompilerConfiguration, extensionConfigs: EnvironmentConfigFiles
): KotlinCoreEnvironment {
val configuration = initialConfiguration.copy()
if (configuration.getList(JVMConfigurationKeys.SCRIPT_DEFINITIONS).isEmpty()) {
// in tests we assume that standard definition should only be added if no other explicit defs are already added
if (!configuration.getBoolean(JVMConfigurationKeys.DISABLE_STANDARD_SCRIPT_DEFINITION) &&
configuration.getList(JVMConfigurationKeys.SCRIPT_DEFINITIONS).isEmpty()
) {
configuration.add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, StandardScriptDefinition)
}
// Tests are supposed to create a single project and dispose it right after use