Refactor script dependnecies template and resolver interfaces:
- get rid of obsolete interfaces and annotations - rename actual resolver interface to ScriptDependenciesResolver - make ScriptDependenciesResolverEx interface compatible with the one from 1.1-M01 to be able to support both on the provider side - add possibility to override file patter in the script template provider - construct resolver lazily, if possible
This commit is contained in:
@@ -31,24 +31,25 @@ import org.jetbrains.kotlin.psi.KtScript
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.Future
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.memberFunctions
|
import kotlin.reflect.memberFunctions
|
||||||
import kotlin.reflect.primaryConstructor
|
import kotlin.reflect.primaryConstructor
|
||||||
|
|
||||||
data class KotlinScriptDefinitionFromTemplate(val template: KClass<out Any>,
|
data class KotlinScriptDefinitionFromTemplate(val template: KClass<out Any>,
|
||||||
val resolver: ScriptDependenciesResolverEx? = null,
|
val resolver: ScriptDependenciesResolver? = null,
|
||||||
|
val scriptFilePattern: String? = null,
|
||||||
val environment: Map<String, Any?>? = null
|
val environment: Map<String, Any?>? = null
|
||||||
) : KotlinScriptDefinition {
|
) : KotlinScriptDefinition {
|
||||||
|
|
||||||
private val log = Logger.getInstance(KotlinScriptDefinitionFromTemplate::class.java)
|
|
||||||
|
|
||||||
// TODO: remove this and simplify definitionAnnotation as soon as deprecated annotations will be removed
|
// TODO: remove this and simplify definitionAnnotation as soon as deprecated annotations will be removed
|
||||||
internal class ScriptTemplateDefinitionData(val resolverClass: KClass<out ScriptDependenciesResolverEx>,
|
internal class ScriptTemplateDefinitionData(val resolverClass: KClass<out ScriptDependenciesResolver>,
|
||||||
val resolver: ScriptDependenciesResolverEx?,
|
makeResolver: () -> ScriptDependenciesResolver?,
|
||||||
val scriptFilePattern: String?) {
|
val scriptFilePattern: String?) {
|
||||||
|
|
||||||
|
val resolver: ScriptDependenciesResolver? by lazy(makeResolver)
|
||||||
|
|
||||||
val acceptedAnnotations: List<KClass<out Annotation>> by lazy {
|
val acceptedAnnotations: List<KClass<out Annotation>> by lazy {
|
||||||
val resolveMethod = ScriptDependenciesResolverEx::resolve
|
val resolveMethod = ScriptDependenciesResolver::resolve
|
||||||
val resolverMethodAnnotations =
|
val resolverMethodAnnotations =
|
||||||
resolverClass.memberFunctions.find {
|
resolverClass.memberFunctions.find {
|
||||||
it.name == resolveMethod.name &&
|
it.name == resolveMethod.name &&
|
||||||
@@ -64,33 +65,14 @@ data class KotlinScriptDefinitionFromTemplate(val template: KClass<out Any>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ObsoleteResolverProxy(val resolverAnn: ScriptDependencyResolver?) : ScriptDependenciesResolverEx {
|
|
||||||
private val resolver by lazy { resolverAnn?.resolver?.primaryConstructor?.call() }
|
|
||||||
override fun resolve(script: ScriptContents,
|
|
||||||
environment: Map<String, Any?>?,
|
|
||||||
report: (ScriptDependenciesResolverEx.ReportSeverity, String, ScriptContents.Position?) -> Unit,
|
|
||||||
previousDependencies: KotlinScriptExternalDependencies?
|
|
||||||
): Future<KotlinScriptExternalDependencies?> =
|
|
||||||
resolver?.resolve(
|
|
||||||
environment?.get("projectRoot") as? File?,
|
|
||||||
script.file,
|
|
||||||
emptyList(),
|
|
||||||
environment as Any?
|
|
||||||
)
|
|
||||||
.asFuture()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val definitionData by lazy {
|
private val definitionData by lazy {
|
||||||
val defAnn = template.annotations.firstIsInstanceOrNull<ScriptTemplateDefinition>()
|
val defAnn = template.annotations.firstIsInstanceOrNull<ScriptTemplateDefinition>()
|
||||||
val obsoleteResolverAnn = template.annotations.firstIsInstanceOrNull<ScriptDependencyResolver>()
|
val filePattern = scriptFilePattern ?: defAnn?.scriptFilePattern ?: DEFAULT_SCRIPT_FILE_PATTERN
|
||||||
val filePattern = defAnn?.scriptFilePattern ?:
|
|
||||||
template.annotations.firstIsInstanceOrNull<ScriptFilePattern>()?.pattern ?:
|
|
||||||
DEFAULT_SCRIPT_FILE_PATTERN
|
|
||||||
when {
|
when {
|
||||||
resolver != null -> ScriptTemplateDefinitionData(resolver.javaClass.kotlin, resolver, filePattern)
|
resolver != null -> ScriptTemplateDefinitionData(resolver.javaClass.kotlin, { resolver }, filePattern)
|
||||||
defAnn != null -> ScriptTemplateDefinitionData(defAnn.resolver, defAnn.resolver.primaryConstructor?.call(), filePattern)
|
// TODO: logScriptDefMessage missing or invalid constructor
|
||||||
obsoleteResolverAnn != null -> ScriptTemplateDefinitionData(ObsoleteResolverProxy::class, ObsoleteResolverProxy(obsoleteResolverAnn), filePattern)
|
defAnn != null -> ScriptTemplateDefinitionData(defAnn.resolver, { defAnn.resolver.primaryConstructor?.call() }, filePattern)
|
||||||
else -> ScriptTemplateDefinitionData(BasicScriptDependenciesResolver::class, BasicScriptDependenciesResolver(), filePattern)
|
else -> ScriptTemplateDefinitionData(BasicScriptDependenciesResolver::class, ::BasicScriptDependenciesResolver, filePattern)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,9 +93,10 @@ data class KotlinScriptDefinitionFromTemplate(val template: KClass<out Any>,
|
|||||||
// TODO: implement other strategy - e.g. try to extract something from match with ScriptFilePattern
|
// TODO: implement other strategy - e.g. try to extract something from match with ScriptFilePattern
|
||||||
override fun getScriptName(script: KtScript): Name = ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT)
|
override fun getScriptName(script: KtScript): Name = ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT)
|
||||||
|
|
||||||
|
|
||||||
override fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? {
|
override fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? {
|
||||||
|
|
||||||
val script = BasicScriptContents(file) {
|
val script = BasicScriptContents(file, getAnnotations = {
|
||||||
val classLoader = (template as Any).javaClass.classLoader
|
val classLoader = (template as Any).javaClass.classLoader
|
||||||
getAnnotationEntries(file, project)
|
getAnnotationEntries(file, project)
|
||||||
.mapNotNull { psiAnn ->
|
.mapNotNull { psiAnn ->
|
||||||
@@ -123,18 +106,9 @@ data class KotlinScriptDefinitionFromTemplate(val template: KClass<out Any>,
|
|||||||
}?.let { KtAnnotationWrapper(psiAnn, classLoader.loadClass(it.qualifiedName).kotlin as KClass<out Annotation>) }
|
}?.let { KtAnnotationWrapper(psiAnn, classLoader.loadClass(it.qualifiedName).kotlin as KClass<out Annotation>) }
|
||||||
}
|
}
|
||||||
.map { it.getProxy(classLoader) }
|
.map { it.getProxy(classLoader) }
|
||||||
}
|
})
|
||||||
val reportFn = { reportSeverity: ScriptDependenciesResolverEx.ReportSeverity, s: String, position: ScriptContents.Position? ->
|
val fileDeps = definitionData.resolver?.resolve(script, environment, ::logScriptDefMessage, previousDependencies)
|
||||||
val msg = (position?.run { "[at $line:$col]" } ?: "") + s
|
// TODO: use it as a Future
|
||||||
when (reportSeverity) {
|
|
||||||
ScriptDependenciesResolverEx.ReportSeverity.ERROR -> log.error(msg)
|
|
||||||
ScriptDependenciesResolverEx.ReportSeverity.WARNING -> log.warn(msg)
|
|
||||||
ScriptDependenciesResolverEx.ReportSeverity.INFO -> log.info(msg)
|
|
||||||
ScriptDependenciesResolverEx.ReportSeverity.DEBUG -> log.debug(msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val fileDeps = definitionData.resolver?.resolve(script, environment, reportFn, previousDependencies)
|
|
||||||
return fileDeps?.get()
|
return fileDeps?.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,4 +138,18 @@ data class KotlinScriptDefinitionFromTemplate(val template: KClass<out Any>,
|
|||||||
override val annotations: Iterable<Annotation> by lazy { getAnnotations() }
|
override val annotations: Iterable<Annotation> by lazy { getAnnotations() }
|
||||||
override val text: CharSequence? by lazy { getFileContents(myFile) }
|
override val text: CharSequence? by lazy { getFileContents(myFile) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
internal val log = Logger.getInstance(KotlinScriptDefinitionFromTemplate::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun logScriptDefMessage(reportSeverity: ScriptDependenciesResolver.ReportSeverity, s: String, position: ScriptContents.Position?): Unit {
|
||||||
|
val msg = (position?.run { "[at $line:$col]" } ?: "") + s
|
||||||
|
when (reportSeverity) {
|
||||||
|
ScriptDependenciesResolver.ReportSeverity.ERROR -> KotlinScriptDefinitionFromTemplate.log.error(msg)
|
||||||
|
ScriptDependenciesResolver.ReportSeverity.WARNING -> KotlinScriptDefinitionFromTemplate.log.warn(msg)
|
||||||
|
ScriptDependenciesResolver.ReportSeverity.INFO -> KotlinScriptDefinitionFromTemplate.log.info(msg)
|
||||||
|
ScriptDependenciesResolver.ReportSeverity.DEBUG -> KotlinScriptDefinitionFromTemplate.log.debug(msg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.script
|
package org.jetbrains.kotlin.script
|
||||||
|
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.Future
|
import java.util.concurrent.Future
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
@@ -28,19 +27,9 @@ const val DEFAULT_SCRIPT_FILE_PATTERN = ".*\\.kts"
|
|||||||
|
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
annotation class ScriptTemplateDefinition(val resolver: KClass<out ScriptDependenciesResolverEx> = BasicScriptDependenciesResolver::class,
|
annotation class ScriptTemplateDefinition(val resolver: KClass<out ScriptDependenciesResolver> = BasicScriptDependenciesResolver::class,
|
||||||
val scriptFilePattern: String = DEFAULT_SCRIPT_FILE_PATTERN)
|
val scriptFilePattern: String = DEFAULT_SCRIPT_FILE_PATTERN)
|
||||||
|
|
||||||
@Deprecated("Use ScriptTemplateDefinition")
|
|
||||||
@Target(AnnotationTarget.CLASS)
|
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
annotation class ScriptFilePattern(val pattern: String)
|
|
||||||
|
|
||||||
@Deprecated("Use ScriptTemplateDefinition")
|
|
||||||
@Target(AnnotationTarget.CLASS)
|
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
annotation class ScriptDependencyResolver(val resolver: KClass<out ScriptDependenciesResolver>)
|
|
||||||
|
|
||||||
interface ScriptContents {
|
interface ScriptContents {
|
||||||
|
|
||||||
data class Position(val line: Int, val col: Int)
|
data class Position(val line: Int, val col: Int)
|
||||||
@@ -60,8 +49,7 @@ class PseudoFuture<T>(private val value: T): Future<T> {
|
|||||||
|
|
||||||
fun KotlinScriptExternalDependencies?.asFuture(): PseudoFuture<KotlinScriptExternalDependencies?> = PseudoFuture(this)
|
fun KotlinScriptExternalDependencies?.asFuture(): PseudoFuture<KotlinScriptExternalDependencies?> = PseudoFuture(this)
|
||||||
|
|
||||||
// TODO: rename to just ScriptDependenciesResolver as soon as current deprecated one will be dropped
|
interface ScriptDependenciesResolver {
|
||||||
interface ScriptDependenciesResolverEx {
|
|
||||||
|
|
||||||
enum class ReportSeverity { ERROR, WARNING, INFO, DEBUG }
|
enum class ReportSeverity { ERROR, WARNING, INFO, DEBUG }
|
||||||
|
|
||||||
@@ -72,16 +60,17 @@ interface ScriptDependenciesResolverEx {
|
|||||||
): Future<KotlinScriptExternalDependencies?> = PseudoFuture(null)
|
): Future<KotlinScriptExternalDependencies?> = PseudoFuture(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Use new ScriptDependenciesResolverEx")
|
@Suppress("unused") // used in gradle-script-kotlin for a moment
|
||||||
interface ScriptDependenciesResolver {
|
@Deprecated("Use new ScriptDependenciesResolver, this one is left for temporary compatibility of new resolvers to kotlin plugin 1.1-M01",
|
||||||
fun resolve(projectRoot: File?,
|
ReplaceWith("ScriptDependenciesResolver"))
|
||||||
scriptFile: File?,
|
interface ScriptDependenciesResolverEx {
|
||||||
annotations: Iterable<KtAnnotationEntry>,
|
fun resolve(script: ScriptContents,
|
||||||
context: Any?
|
environment: Map<String, Any?>?,
|
||||||
|
previousDependencies: KotlinScriptExternalDependencies?
|
||||||
): KotlinScriptExternalDependencies? = null
|
): KotlinScriptExternalDependencies? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
class BasicScriptDependenciesResolver : ScriptDependenciesResolverEx
|
class BasicScriptDependenciesResolver : ScriptDependenciesResolver
|
||||||
|
|
||||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
|||||||
+4
-2
@@ -32,7 +32,9 @@ interface ScriptTemplateProvider {
|
|||||||
|
|
||||||
val templateClassName: String
|
val templateClassName: String
|
||||||
|
|
||||||
val resolver: ScriptDependenciesResolverEx? get() = null
|
val resolver: ScriptDependenciesResolver? get() = null
|
||||||
|
|
||||||
|
val filePattern: String? get() = null
|
||||||
|
|
||||||
val dependenciesClasspath: Iterable<String>
|
val dependenciesClasspath: Iterable<String>
|
||||||
|
|
||||||
@@ -58,7 +60,7 @@ fun makeScriptDefsFromTemplateProviders(providers: Iterable<ScriptTemplateProvid
|
|||||||
val loader = URLClassLoader(provider.dependenciesClasspath.map { File(it).toURI().toURL() }.toTypedArray(), ScriptTemplateProvider::class.java.classLoader)
|
val loader = URLClassLoader(provider.dependenciesClasspath.map { File(it).toURI().toURL() }.toTypedArray(), ScriptTemplateProvider::class.java.classLoader)
|
||||||
val cl = loader.loadClass(provider.templateClassName)
|
val cl = loader.loadClass(provider.templateClassName)
|
||||||
idToVersion.put(provider.id, provider.version)
|
idToVersion.put(provider.id, provider.version)
|
||||||
KotlinScriptDefinitionFromTemplate(cl.kotlin, provider.resolver, provider.environment)
|
KotlinScriptDefinitionFromTemplate(cl.kotlin, provider.resolver, provider.filePattern, provider.environment)
|
||||||
}
|
}
|
||||||
catch (ex: Exception) {
|
catch (ex: Exception) {
|
||||||
errorsHandler(provider, ex)
|
errorsHandler(provider, ex)
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class ScriptTest2 {
|
|||||||
environment: Map<String, Any?>? = null,
|
environment: Map<String, Any?>? = null,
|
||||||
runIsolated: Boolean = true,
|
runIsolated: Boolean = true,
|
||||||
suppressOutput: Boolean = false): Class<*>? =
|
suppressOutput: Boolean = false): Class<*>? =
|
||||||
compileScriptImpl("compiler/testData/script/" + scriptPath, KotlinScriptDefinitionFromTemplate(scriptBase, null, environment), runIsolated, suppressOutput)
|
compileScriptImpl("compiler/testData/script/" + scriptPath, KotlinScriptDefinitionFromTemplate(scriptBase, null, null, environment), runIsolated, suppressOutput)
|
||||||
|
|
||||||
private fun compileScriptImpl(
|
private fun compileScriptImpl(
|
||||||
scriptPath: String,
|
scriptPath: String,
|
||||||
@@ -126,14 +126,14 @@ class ScriptTest2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestKotlinScriptDependenciesResolver : ScriptDependenciesResolverEx {
|
class TestKotlinScriptDependenciesResolver : ScriptDependenciesResolver {
|
||||||
|
|
||||||
private val kotlinPaths by lazy { PathUtil.getKotlinPathsForCompiler() }
|
private val kotlinPaths by lazy { PathUtil.getKotlinPathsForCompiler() }
|
||||||
|
|
||||||
@AcceptedAnnotations(DependsOn::class, DependsOnTwo::class)
|
@AcceptedAnnotations(DependsOn::class, DependsOnTwo::class)
|
||||||
override fun resolve(script: ScriptContents,
|
override fun resolve(script: ScriptContents,
|
||||||
environment: Map<String, Any?>?,
|
environment: Map<String, Any?>?,
|
||||||
report: (ScriptDependenciesResolverEx.ReportSeverity, String, ScriptContents.Position?) -> Unit,
|
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit,
|
||||||
previousDependencies: KotlinScriptExternalDependencies?
|
previousDependencies: KotlinScriptExternalDependencies?
|
||||||
): Future<KotlinScriptExternalDependencies?>
|
): Future<KotlinScriptExternalDependencies?>
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user