Implement additional compiler arguments support in scripts

This commit is contained in:
Ilya Chernikov
2019-01-09 18:23:33 +01:00
parent 04b04ea0ee
commit 7ee9801c5f
5 changed files with 322 additions and 112 deletions
@@ -22,7 +22,8 @@ import kotlin.script.experimental.jvm.compat.mapToLegacyScriptReportSeverity
class BridgeDependenciesResolver(
val scriptCompilationConfiguration: ScriptCompilationConfiguration,
val onClasspathUpdated: (List<File>) -> Unit = {}
val onConfigurationUpdated: (SourceCode, ScriptCompilationConfiguration) -> Unit = { _, _ -> },
val getScriptSource: (ScriptContents) -> SourceCode? = { null }
) : AsyncDependenciesResolver {
override fun resolve(scriptContents: ScriptContents, environment: Environment): DependenciesResolver.ResolveResult =
@@ -40,9 +41,6 @@ class BridgeDependenciesResolver(
)
)
val oldClasspath =
scriptCompilationConfiguration[ScriptCompilationConfiguration.dependencies].toClassPathOrEmpty()
val defaultImports = scriptCompilationConfiguration[ScriptCompilationConfiguration.defaultImports]?.toList() ?: emptyList()
fun ScriptCompilationConfiguration.toDependencies(classpath: List<File>): ScriptDependencies =
@@ -53,13 +51,15 @@ class BridgeDependenciesResolver(
scripts = this[ScriptCompilationConfiguration.importScripts].toFilesOrEmpty()
)
val script = getScriptSource(scriptContents) ?: scriptContents.toScriptSource()
val refineResults = scriptCompilationConfiguration.refineWith(
scriptCompilationConfiguration[ScriptCompilationConfiguration.refineConfigurationOnAnnotations]?.handler,
scriptContents, processedScriptData
processedScriptData, script
).onSuccess {
it.refineWith(
scriptCompilationConfiguration[ScriptCompilationConfiguration.refineConfigurationBeforeCompiling]?.handler,
scriptContents, processedScriptData
processedScriptData, script
)
}
@@ -72,11 +72,12 @@ class BridgeDependenciesResolver(
}
}
if (refinedConfiguration != scriptCompilationConfiguration) {
onConfigurationUpdated(script, refinedConfiguration)
}
val newClasspath = refinedConfiguration[ScriptCompilationConfiguration.dependencies]
?.flatMap { (it as JvmDependency).classpath } ?: emptyList()
if (newClasspath != oldClasspath) {
onClasspathUpdated(newClasspath)
}
return DependenciesResolver.ResolveResult.Success(
// TODO: consider returning only increment from the initial config
@@ -109,12 +110,9 @@ internal fun List<SourceCode>?.toFilesOrEmpty() = this?.map {
} ?: emptyList()
fun ScriptCompilationConfiguration.refineWith(
handler: RefineScriptCompilationConfigurationHandler?, scriptContents: ScriptContents, processedScriptData: ScriptCollectedData
): ResultWithDiagnostics<ScriptCompilationConfiguration> {
if (handler == null) return this.asSuccess()
return handler(
ScriptConfigurationRefinementContext(scriptContents.toScriptSource(), this, processedScriptData)
)
}
handler: RefineScriptCompilationConfigurationHandler?,
processedScriptData: ScriptCollectedData,
script: SourceCode
): ResultWithDiagnostics<ScriptCompilationConfiguration> =
if (handler == null) this.asSuccess()
else handler(ScriptConfigurationRefinementContext(script, this, processedScriptData))
@@ -77,6 +77,19 @@ fun getResourcePathForClass(aClass: Class<*>): File {
return File(resourceRoot).absoluteFile
}
fun tryGetResourcePathForClassByName(name: String, classLoader: ClassLoader): File? = try {
classLoader.loadClass(name)?.let {
val path = "/" + name.replace('.', '/') + ".class"
getResourceRoot(it, path)
}?.let {
File(it).absoluteFile
}
} catch (_: ClassNotFoundException) {
null
} catch (_: NoClassDefFoundError) {
null
}
internal fun URL.toFile() =
try {
File(toURI().schemeSpecificPart)
@@ -12,6 +12,7 @@ import java.net.URLClassLoader
import kotlin.reflect.KClass
import kotlin.script.experimental.jvm.impl.getResourcePathForClass
import kotlin.script.experimental.jvm.impl.toFile
import kotlin.script.experimental.jvm.impl.tryGetResourcePathForClassByName
import kotlin.script.templates.standard.ScriptTemplateWithArgs
// TODO: consider moving all these utilites to the build-common or some other shared compiler API module
@@ -29,6 +30,7 @@ internal const val KOTLIN_SCRIPT_CLASSPATH_PROPERTY = "kotlin.script.classpath"
internal const val KOTLIN_COMPILER_CLASSPATH_PROPERTY = "kotlin.compiler.classpath"
internal const val KOTLIN_COMPILER_JAR_PROPERTY = "kotlin.compiler.jar"
internal const val KOTLIN_STDLIB_JAR_PROPERTY = "kotlin.java.stdlib.jar"
internal const val KOTLIN_REFLECT_JAR_PROPERTY = "kotlin.java.reflect.jar"
// obsolete name, but maybe still used in the wild
// TODO: consider removing
internal const val KOTLIN_RUNTIME_JAR_PROPERTY = "kotlin.java.runtime.jar"
@@ -189,6 +191,11 @@ object KotlinJars {
?: explicitCompilerClasspath?.firstOrNull { it.matchMaybeVersionedFile(jarName) }?.takeIf(File::exists)
?: getResourcePathForClass(markerClass.java).takeIf(File::exists)
fun getLib(propertyName: String, jarName: String, markerClassName: String): File? =
System.getProperty(propertyName)?.let(::File)?.takeIf(File::exists)
?: explicitCompilerClasspath?.firstOrNull { it.matchMaybeVersionedFile(jarName) }?.takeIf(File::exists)
?: tryGetResourcePathForClassByName(markerClassName, Thread.currentThread().contextClassLoader)?.takeIf(File::exists)
val stdlibOrNull: File? by lazy {
System.getProperty(KOTLIN_STDLIB_JAR_PROPERTY)?.let(::File)?.takeIf(File::exists)
?: getLib(
@@ -203,6 +210,14 @@ object KotlinJars {
?: throw Exception("Unable to find kotlin stdlib, please specify it explicitly via \"$KOTLIN_STDLIB_JAR_PROPERTY\" property")
}
val reflectOrNull: File? by lazy {
getLib(
KOTLIN_REFLECT_JAR_PROPERTY,
KOTLIN_JAVA_REFLECT_JAR,
"kotlin.reflect.full.IllegalCallableAccessException"
)
}
val scriptRuntimeOrNull: File? by lazy {
getLib(
KOTLIN_SCRIPT_RUNTIME_JAR_PROPERTY,