ScriptTemplatesProvider: refactor dependency loading

Change dependenciesClasspath is of type List<File>
Add additionalResolverClasspath
This commit is contained in:
Pavel V. Talanov
2017-07-11 15:56:18 +03:00
parent a77cd0ab09
commit 6c3ce7adc1
5 changed files with 19 additions and 11 deletions
@@ -42,7 +42,15 @@ interface ScriptTemplatesProvider {
val filePattern: String? get() = null val filePattern: String? get() = null
val dependenciesClasspath: Iterable<String> val dependenciesClasspath: List<File>
// TODO: need to provide a way to specify this in compiler/repl .. etc
/*
* Allows to specify additional jars needed for DependenciesResolver (and not script template).
* Script template dependencies naturally become (part of) dependencies of the script which is not always desired for resolver dependencies.
* i.e. gradle resolver may depend on some jars that 'built.gradle.kts' files should not depend on.
*/
val additionalResolverClasspath: List<File> get() = emptyList()
val environment: Map<String, Any?>? val environment: Map<String, Any?>?
@@ -65,9 +73,10 @@ fun makeScriptDefsFromTemplatesProviders(providers: Iterable<ScriptTemplatesProv
errorsHandler: ((ScriptTemplatesProvider, Throwable) -> Unit) = { _, ex -> throw ex } errorsHandler: ((ScriptTemplatesProvider, Throwable) -> Unit) = { _, ex -> throw ex }
): List<KotlinScriptDefinition> = providers.flatMap { provider -> ): List<KotlinScriptDefinition> = providers.flatMap { provider ->
try { try {
LOG.info("[kts] loading script definitions ${provider.templateClassNames} using cp: ${provider.dependenciesClasspath.joinToString(File.pathSeparator)}") val classpath = provider.dependenciesClasspath + provider.additionalResolverClasspath
LOG.info("[kts] loading script definitions ${provider.templateClassNames} using cp: ${classpath.joinToString(File.pathSeparator)}")
provider.scriptDefinitions ?: run { provider.scriptDefinitions ?: run {
val loader = URLClassLoader(provider.dependenciesClasspath.map { File(it).toURI().toURL() }.toTypedArray(), ScriptTemplatesProvider::class.java.classLoader) val loader = URLClassLoader(classpath.map { it.toURI().toURL() }.toTypedArray(), ScriptTemplatesProvider::class.java.classLoader)
provider.templateClassNames.map { provider.templateClassNames.map {
KotlinScriptDefinitionFromAnnotatedTemplate(loader.loadClass(it).kotlin, provider.resolver, provider.filePattern, provider.environment) KotlinScriptDefinitionFromAnnotatedTemplate(loader.loadClass(it).kotlin, provider.resolver, provider.filePattern, provider.environment)
} }
@@ -62,7 +62,7 @@ class GradleScriptTemplatesProvider(project: Project): ScriptTemplatesProvider {
private sealed class TemplateDataOrError { private sealed class TemplateDataOrError {
class Data(val templateClassNames: Iterable<String>, class Data(val templateClassNames: Iterable<String>,
val dependenciesClasspath: Iterable<File>, val dependenciesClasspath: List<File>,
val scriptDefinitions: List<KotlinScriptDefinition>) : TemplateDataOrError() val scriptDefinitions: List<KotlinScriptDefinition>) : TemplateDataOrError()
class Error(val message: String) : TemplateDataOrError() class Error(val message: String) : TemplateDataOrError()
} }
@@ -83,7 +83,7 @@ class GradleScriptTemplatesProvider(project: Project): ScriptTemplatesProvider {
try { try {
val cl = loader.loadClass(template) val cl = loader.loadClass(template)
val def = KotlinScriptDefinitionFromAnnotatedTemplate(cl.kotlin, resolver, filePattern, environment) val def = KotlinScriptDefinitionFromAnnotatedTemplate(cl.kotlin, resolver, filePattern, environment)
return@lazy TemplateDataOrError.Data(listOf(template), cp.asIterable(), listOf(def)) return@lazy TemplateDataOrError.Data(listOf(template), cp.asList(), listOf(def))
} }
catch (e: ClassNotFoundException) {} catch (e: ClassNotFoundException) {}
catch (e: NoClassDefFoundError) {} catch (e: NoClassDefFoundError) {}
@@ -97,8 +97,8 @@ class GradleScriptTemplatesProvider(project: Project): ScriptTemplatesProvider {
is GradleScriptTemplatesProvider.TemplateDataOrError.Error -> throw IllegalStateException((templatesData as TemplateDataOrError.Error).message) is GradleScriptTemplatesProvider.TemplateDataOrError.Error -> throw IllegalStateException((templatesData as TemplateDataOrError.Error).message)
} }
override val dependenciesClasspath: Iterable<String> get() = when(templatesData) { override val dependenciesClasspath: List<File> get() = when(templatesData) {
is GradleScriptTemplatesProvider.TemplateDataOrError.Data -> (templatesData as TemplateDataOrError.Data).dependenciesClasspath.map { it.canonicalPath } is GradleScriptTemplatesProvider.TemplateDataOrError.Data -> (templatesData as TemplateDataOrError.Data).dependenciesClasspath
is GradleScriptTemplatesProvider.TemplateDataOrError.Error -> throw IllegalStateException((templatesData as TemplateDataOrError.Error).message) is GradleScriptTemplatesProvider.TemplateDataOrError.Error -> throw IllegalStateException((templatesData as TemplateDataOrError.Error).message)
} }
@@ -33,7 +33,7 @@ class StandardKotlinScriptTemplateProvider(val project: Project) : ScriptTemplat
override val isValid: Boolean = true override val isValid: Boolean = true
override val templateClassNames: Iterable<String> get() = listOf(ScriptTemplateWithArgs::class.qualifiedName!!) override val templateClassNames: Iterable<String> get() = listOf(ScriptTemplateWithArgs::class.qualifiedName!!)
override val dependenciesClasspath: Iterable<String> get() = emptyList() override val dependenciesClasspath get() = emptyList<File>()
override val environment: Map<String, Any?>? get() { override val environment: Map<String, Any?>? get() {
return mapOf( return mapOf(
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.idea.script
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettings import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettings
import org.jetbrains.kotlin.idea.core.script.topLevelSectionCodeTextTokens
import org.jetbrains.kotlin.script.ScriptTemplatesProvider import org.jetbrains.kotlin.script.ScriptTemplatesProvider
import java.io.File import java.io.File
@@ -30,7 +29,7 @@ class ScriptTemplatesFromCompilerSettingsProvider(project: Project): ScriptTempl
override val isValid: Boolean = kotlinSettings.scriptTemplates.isNotBlank() override val isValid: Boolean = kotlinSettings.scriptTemplates.isNotBlank()
override val templateClassNames: Iterable<String> get() = kotlinSettings.scriptTemplates.split(',', ' ') override val templateClassNames: Iterable<String> get() = kotlinSettings.scriptTemplates.split(',', ' ')
override val dependenciesClasspath: Iterable<String> get() = kotlinSettings.scriptTemplatesClasspath.split(File.pathSeparator) override val dependenciesClasspath get() = kotlinSettings.scriptTemplatesClasspath.split(File.pathSeparator).map(::File)
override val environment: Map<String, Any?>? by lazy { mapOf( override val environment: Map<String, Any?>? by lazy { mapOf(
"projectRoot" to (project.basePath ?: project.baseDir.canonicalPath)?.let(::File)) "projectRoot" to (project.basePath ?: project.baseDir.canonicalPath)?.let(::File))
} }
@@ -143,5 +143,5 @@ class TestScriptTemplateProvider(
override val id = "Test" override val id = "Test"
override val isValid = true override val isValid = true
override val templateClassNames = listOf("custom.scriptDefinition.Template") override val templateClassNames = listOf("custom.scriptDefinition.Template")
override val dependenciesClasspath = listOf(compiledTemplateDir.canonicalPath) override val dependenciesClasspath = listOf(compiledTemplateDir)
} }