Refactor script resolving interface
- return Future from resovler - pack script contents data to a separate interface -extend script dependencies with additional scripts property - minor renames and moves
This commit is contained in:
+20
-18
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.utils.KotlinPaths
|
|||||||
import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir
|
import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.concurrent.Future
|
||||||
|
|
||||||
|
|
||||||
data class KotlinConfigurableScriptDefinition(val config: KotlinScriptConfig, val environmentVars: Map<String, List<String>>?) : KotlinScriptDefinition {
|
data class KotlinConfigurableScriptDefinition(val config: KotlinScriptConfig, val environmentVars: Map<String, List<String>>?) : KotlinScriptDefinition {
|
||||||
@@ -46,24 +47,25 @@ data class KotlinConfigurableScriptDefinition(val config: KotlinScriptConfig, va
|
|||||||
|
|
||||||
private val evaluatedClasspath by lazy { config.classpath.evalWithVars(environmentVars).map { File(it) }.distinctBy { it.canonicalPath } }
|
private val evaluatedClasspath by lazy { config.classpath.evalWithVars(environmentVars).map { File(it) }.distinctBy { it.canonicalPath } }
|
||||||
|
|
||||||
override fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? =
|
override fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): Future<KotlinScriptExternalDependencies>? =
|
||||||
if (!isScript(file)) null
|
makeNullableFakeFuture(
|
||||||
else {
|
if (!isScript(file)) null
|
||||||
val extDeps = getScriptDependenciesFromConfig(file)
|
else {
|
||||||
when {
|
val extDeps = getScriptDependenciesFromConfig(file)
|
||||||
extDeps != null ->
|
when {
|
||||||
object : KotlinScriptExternalDependencies {
|
extDeps != null ->
|
||||||
override val classpath: Iterable<File> = evaluatedClasspath + extDeps.classpath
|
object : KotlinScriptExternalDependencies {
|
||||||
override val imports = extDeps.imports
|
override val classpath: Iterable<File> = evaluatedClasspath + extDeps.classpath
|
||||||
override val sources: Iterable<File> = extDeps.sources
|
override val imports = extDeps.imports
|
||||||
}
|
override val sources: Iterable<File> = extDeps.sources
|
||||||
!evaluatedClasspath.isEmpty() ->
|
}
|
||||||
object : KotlinScriptExternalDependencies {
|
!evaluatedClasspath.isEmpty() ->
|
||||||
override val classpath: Iterable<File> = evaluatedClasspath
|
object : KotlinScriptExternalDependencies {
|
||||||
}
|
override val classpath: Iterable<File> = evaluatedClasspath
|
||||||
else -> null
|
}
|
||||||
}
|
else -> null
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ package org.jetbrains.kotlin.script
|
|||||||
|
|
||||||
import com.intellij.openapi.fileTypes.LanguageFileType
|
import com.intellij.openapi.fileTypes.LanguageFileType
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
|
||||||
import com.intellij.psi.PsiFile
|
|
||||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
@@ -35,6 +33,8 @@ import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.concurrent.Future
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
interface KotlinScriptDefinition {
|
interface KotlinScriptDefinition {
|
||||||
@@ -54,44 +54,25 @@ interface KotlinScriptDefinition {
|
|||||||
fun getScriptName(script: KtScript): Name =
|
fun getScriptName(script: KtScript): Name =
|
||||||
ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT)
|
ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT)
|
||||||
|
|
||||||
fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? = null
|
fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): Future<KotlinScriptExternalDependencies>? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
interface KotlinScriptExternalDependencies {
|
interface KotlinScriptExternalDependencies {
|
||||||
val classpath: Iterable<File> get() = emptyList()
|
val classpath: Iterable<File> get() = emptyList()
|
||||||
val imports: Iterable<String> get() = emptyList()
|
val imports: Iterable<String> get() = emptyList()
|
||||||
val sources: Iterable<File> get() = emptyList()
|
val sources: Iterable<File> get() = emptyList()
|
||||||
|
val scripts: Iterable<File> get() = emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
class KotlinScriptExternalDependenciesUnion(val dependencies: Iterable<KotlinScriptExternalDependencies>) : KotlinScriptExternalDependencies {
|
class KotlinScriptExternalDependenciesUnion(val dependencies: Iterable<KotlinScriptExternalDependencies>) : KotlinScriptExternalDependencies {
|
||||||
override val classpath: Iterable<File> get() = dependencies.flatMap { it.classpath }
|
override val classpath: Iterable<File> get() = dependencies.flatMap { it.classpath }
|
||||||
override val imports: Iterable<String> get() = dependencies.flatMap { it.imports }
|
override val imports: Iterable<String> get() = dependencies.flatMap { it.imports }
|
||||||
override val sources: Iterable<File> get() = dependencies.flatMap { it.sources }
|
override val sources: Iterable<File> get() = dependencies.flatMap { it.sources }
|
||||||
|
override val scripts: Iterable<File> get() = dependencies.flatMap { it.scripts }
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ScriptParameter(val name: Name, val type: KotlinType)
|
data class ScriptParameter(val name: Name, val type: KotlinType)
|
||||||
|
|
||||||
fun <TF> getFileName(file: TF): String = when (file) {
|
|
||||||
is PsiFile -> file.originalFile.name
|
|
||||||
is VirtualFile -> file.name
|
|
||||||
is File -> file.name
|
|
||||||
else -> throw IllegalArgumentException("Unsupported file type $file")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <TF> getFilePath(file: TF): String = when (file) {
|
|
||||||
is PsiFile -> file.originalFile.run { virtualFile?.path ?: name } // TODO: replace name with path of PSI elements
|
|
||||||
is VirtualFile -> file.path
|
|
||||||
is File -> file.canonicalPath
|
|
||||||
else -> throw IllegalArgumentException("Unsupported file type $file")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <TF> getFile(file: TF): File? = when (file) {
|
|
||||||
is PsiFile -> file.originalFile.run { File(virtualFile?.path) }
|
|
||||||
is VirtualFile -> File(file.path)
|
|
||||||
is File -> file
|
|
||||||
else -> throw IllegalArgumentException("Unsupported file type $file")
|
|
||||||
}
|
|
||||||
|
|
||||||
object StandardScriptDefinition : KotlinScriptDefinition {
|
object StandardScriptDefinition : KotlinScriptDefinition {
|
||||||
private val ARGS_NAME = Name.identifier("args")
|
private val ARGS_NAME = Name.identifier("args")
|
||||||
|
|
||||||
@@ -119,3 +100,14 @@ fun getKotlinTypeByFqName(scriptDescriptor: ScriptDescriptor, fqName: String): K
|
|||||||
ClassId.topLevel(FqName(fqName)),
|
ClassId.topLevel(FqName(fqName)),
|
||||||
NotFoundClasses(LockBasedStorageManager.NO_LOCKS, scriptDescriptor.module)
|
NotFoundClasses(LockBasedStorageManager.NO_LOCKS, scriptDescriptor.module)
|
||||||
).defaultType
|
).defaultType
|
||||||
|
|
||||||
|
class FakeFuture<T: Any?>(val value: T) : Future<T> {
|
||||||
|
override fun isCancelled(): Boolean = false
|
||||||
|
override fun cancel(mayInterruptIfRunning: Boolean): Boolean = false
|
||||||
|
override fun get(): T = value
|
||||||
|
override fun get(timeout: Long, unit: TimeUnit): T = value
|
||||||
|
override fun isDone(): Boolean = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T: Any> makeNullableFakeFuture(value: T?): Future<T>? =
|
||||||
|
value?.let { FakeFuture(it) } ?: (null as Future<T>?)
|
||||||
|
|||||||
+3
-3
@@ -37,7 +37,7 @@ class KotlinScriptExternalImportsProvider(val project: Project, private val scri
|
|||||||
cache[path]
|
cache[path]
|
||||||
?: if (cacheOfNulls.contains(path)) null
|
?: if (cacheOfNulls.contains(path)) null
|
||||||
else scriptDefinitionProvider.findScriptDefinition(file)
|
else scriptDefinitionProvider.findScriptDefinition(file)
|
||||||
?.let { it.getDependenciesFor(file, project, null) }
|
?.let { it.getDependenciesFor(file, project, null)?.get() }
|
||||||
.apply { cacheLock.write {
|
.apply { cacheLock.write {
|
||||||
if (this == null) {
|
if (this == null) {
|
||||||
cacheOfNulls.add(path)
|
cacheOfNulls.add(path)
|
||||||
@@ -58,7 +58,7 @@ class KotlinScriptExternalImportsProvider(val project: Project, private val scri
|
|||||||
if (!cache.containsKey(path) && !cacheOfNulls.contains(path) && !uncached.contains(path)) {
|
if (!cache.containsKey(path) && !cacheOfNulls.contains(path) && !uncached.contains(path)) {
|
||||||
val scriptDef = scriptDefinitionProvider.findScriptDefinition(file)
|
val scriptDef = scriptDefinitionProvider.findScriptDefinition(file)
|
||||||
if (scriptDef != null) {
|
if (scriptDef != null) {
|
||||||
val deps = scriptDef.getDependenciesFor(file, project, null)
|
val deps = scriptDef.getDependenciesFor(file, project, null)?.get()
|
||||||
if (deps != null) {
|
if (deps != null) {
|
||||||
cache.put(path, deps)
|
cache.put(path, deps)
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ class KotlinScriptExternalImportsProvider(val project: Project, private val scri
|
|||||||
val scriptDef = scriptDefinitionProvider.findScriptDefinition(file)
|
val scriptDef = scriptDefinitionProvider.findScriptDefinition(file)
|
||||||
if (scriptDef != null) {
|
if (scriptDef != null) {
|
||||||
val oldDeps = cache[path]
|
val oldDeps = cache[path]
|
||||||
val deps = scriptDef.getDependenciesFor(file, project, oldDeps)
|
val deps = scriptDef.getDependenciesFor(file, project, oldDeps)?.get()
|
||||||
when {
|
when {
|
||||||
deps != null && (oldDeps == null ||
|
deps != null && (oldDeps == null ||
|
||||||
!deps.classpath.isSamePathListAs(oldDeps.classpath) || !deps.sources.isSamePathListAs(oldDeps.sources)) -> {
|
!deps.classpath.isSamePathListAs(oldDeps.classpath) || !deps.sources.isSamePathListAs(oldDeps.sources)) -> {
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.script
|
||||||
|
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
fun <TF> getFileName(file: TF): String = when (file) {
|
||||||
|
is PsiFile -> file.originalFile.name
|
||||||
|
is VirtualFile -> file.name
|
||||||
|
is File -> file.name
|
||||||
|
else -> throw IllegalArgumentException("Unsupported file type $file")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <TF> getFilePath(file: TF): String = when (file) {
|
||||||
|
is PsiFile -> file.originalFile.run { virtualFile?.path ?: name } // TODO: replace name with path of PSI elements
|
||||||
|
is VirtualFile -> file.path
|
||||||
|
is File -> file.canonicalPath
|
||||||
|
else -> throw IllegalArgumentException("Unsupported file type $file")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <TF> getFile(file: TF): File? = when (file) {
|
||||||
|
is PsiFile -> file.originalFile.run { File(virtualFile?.path) }
|
||||||
|
is VirtualFile -> File(file.path)
|
||||||
|
is File -> file
|
||||||
|
else -> throw IllegalArgumentException("Unsupported file type $file")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <TF> getFileContents(file: TF): CharSequence = when (file) {
|
||||||
|
is PsiFile -> file.viewProvider.contents
|
||||||
|
is VirtualFile -> file.inputStream.reader(charset = file.charset).readText()
|
||||||
|
is File -> file.readText()
|
||||||
|
else -> throw IllegalArgumentException("Unsupported file type $file")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <TF> getFileContentsStream(file: TF): InputStream = when (file) {
|
||||||
|
is PsiFile -> file.viewProvider.contents.toString().byteInputStream()
|
||||||
|
is VirtualFile -> file.inputStream
|
||||||
|
is File -> file.inputStream()
|
||||||
|
else -> throw IllegalArgumentException("Unsupported file type $file")
|
||||||
|
}
|
||||||
|
|
||||||
@@ -30,15 +30,17 @@ 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.io.InputStream
|
||||||
import java.lang.reflect.InvocationHandler
|
import java.lang.reflect.InvocationHandler
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
import java.lang.reflect.Proxy
|
import java.lang.reflect.Proxy
|
||||||
|
import java.util.concurrent.Future
|
||||||
import kotlin.reflect.*
|
import kotlin.reflect.*
|
||||||
|
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
annotation class ScriptTemplateDefinition(val resolver: KClass<out AnnotationBasedScriptDependenciesResolver>,
|
annotation class ScriptTemplateDefinition(val resolver: KClass<out ScriptDependenciesResolverEx> = BasicScriptDependenciesResolver::class,
|
||||||
val scriptFilePattern: String)
|
val scriptFilePattern: String = "*.\\.kts")
|
||||||
|
|
||||||
@Deprecated("Use ScriptTemplateDefinition")
|
@Deprecated("Use ScriptTemplateDefinition")
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@@ -50,15 +52,22 @@ annotation class ScriptFilePattern(val pattern: String)
|
|||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
annotation class ScriptDependencyResolver(val resolver: KClass<out ScriptDependenciesResolver>)
|
annotation class ScriptDependencyResolver(val resolver: KClass<out ScriptDependenciesResolver>)
|
||||||
|
|
||||||
interface AnnotationBasedScriptDependenciesResolver {
|
interface ScriptContents {
|
||||||
fun resolve(scriptFile: File?,
|
val file: File?
|
||||||
annotations: Iterable<Annotation>,
|
val annotations: Iterable<Annotation>
|
||||||
environment: Map<String, Any?>?,
|
val contents: CharSequence?
|
||||||
previousDependencies: KotlinScriptExternalDependencies? = null
|
val contentsStream: InputStream?
|
||||||
): KotlinScriptExternalDependencies? = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Use new resolver Ex")
|
// TODO: rename to just ScriptDependenciesResolver as soon as current deprecated one will be dropped
|
||||||
|
interface ScriptDependenciesResolverEx {
|
||||||
|
fun resolve(script: ScriptContents,
|
||||||
|
environment: Map<String, Any?>?,
|
||||||
|
previousDependencies: KotlinScriptExternalDependencies? = null
|
||||||
|
): Future<KotlinScriptExternalDependencies>? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use new ScriptDependenciesResolverEx")
|
||||||
interface ScriptDependenciesResolver {
|
interface ScriptDependenciesResolver {
|
||||||
fun resolve(projectRoot: File?,
|
fun resolve(projectRoot: File?,
|
||||||
scriptFile: File?,
|
scriptFile: File?,
|
||||||
@@ -67,6 +76,8 @@ interface ScriptDependenciesResolver {
|
|||||||
): KotlinScriptExternalDependencies? = null
|
): KotlinScriptExternalDependencies? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BasicScriptDependenciesResolver : ScriptDependenciesResolverEx
|
||||||
|
|
||||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
annotation class AcceptedAnnotations(vararg val supportedAnnotationClasses: KClass<out Annotation>)
|
annotation class AcceptedAnnotations(vararg val supportedAnnotationClasses: KClass<out Annotation>)
|
||||||
@@ -74,11 +85,11 @@ annotation class AcceptedAnnotations(vararg val supportedAnnotationClasses: KCla
|
|||||||
data class KotlinScriptDefinitionFromTemplate(val template: KClass<out Any>, val environment: Map<String, Any?>?) : KotlinScriptDefinition {
|
data class KotlinScriptDefinitionFromTemplate(val template: KClass<out Any>, val environment: Map<String, Any?>?) : KotlinScriptDefinition {
|
||||||
|
|
||||||
// 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 AnnotationBasedScriptDependenciesResolver>,
|
internal class ScriptTemplateDefinitionData(val resolverClass: KClass<out ScriptDependenciesResolverEx>,
|
||||||
val resolver: AnnotationBasedScriptDependenciesResolver?,
|
val resolver: ScriptDependenciesResolverEx?,
|
||||||
val scriptFilePattern: String?) {
|
val scriptFilePattern: String?) {
|
||||||
val acceptedAnnotations by lazy {
|
val acceptedAnnotations: List<KClass<out Annotation>> by lazy {
|
||||||
val resolveMethod = AnnotationBasedScriptDependenciesResolver::resolve
|
val resolveMethod = ScriptDependenciesResolverEx::resolve
|
||||||
val resolverMethodAnnotations =
|
val resolverMethodAnnotations =
|
||||||
resolverClass.memberFunctions.find {
|
resolverClass.memberFunctions.find {
|
||||||
it.name == resolveMethod.name &&
|
it.name == resolveMethod.name &&
|
||||||
@@ -94,19 +105,18 @@ data class KotlinScriptDefinitionFromTemplate(val template: KClass<out Any>, val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ObsoleteResolverProxy(val resolverAnn: ScriptDependencyResolver?) : AnnotationBasedScriptDependenciesResolver {
|
internal class ObsoleteResolverProxy(val resolverAnn: ScriptDependencyResolver?) : ScriptDependenciesResolverEx {
|
||||||
private val resolver by lazy { resolverAnn?.resolver?.primaryConstructor?.call() }
|
private val resolver by lazy { resolverAnn?.resolver?.primaryConstructor?.call() }
|
||||||
override fun resolve(scriptFile: File?,
|
override fun resolve(script: ScriptContents,
|
||||||
annotations: Iterable<Annotation>,
|
|
||||||
environment: Map<String, Any?>?,
|
environment: Map<String, Any?>?,
|
||||||
previousDependencies: KotlinScriptExternalDependencies?
|
previousDependencies: KotlinScriptExternalDependencies?
|
||||||
): KotlinScriptExternalDependencies? =
|
): Future<KotlinScriptExternalDependencies>? = makeNullableFakeFuture(
|
||||||
resolver?.resolve(
|
resolver?.resolve(
|
||||||
environment?.get("projectRoot") as? File?,
|
environment?.get("projectRoot") as? File?,
|
||||||
scriptFile,
|
script.file,
|
||||||
emptyList(),
|
emptyList(),
|
||||||
environment as Any?
|
environment as Any?
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
private val definitionData by lazy {
|
private val definitionData by lazy {
|
||||||
@@ -136,7 +146,7 @@ data class KotlinScriptDefinitionFromTemplate(val template: KClass<out Any>, val
|
|||||||
// 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?): Future<KotlinScriptExternalDependencies>? {
|
||||||
val fileAnnotations = getAnnotationEntries(file, project)
|
val fileAnnotations = getAnnotationEntries(file, project)
|
||||||
.map { KtAnnotationWrapper(it) }
|
.map { KtAnnotationWrapper(it) }
|
||||||
.mapNotNull { wrappedAnn ->
|
.mapNotNull { wrappedAnn ->
|
||||||
@@ -159,7 +169,7 @@ data class KotlinScriptDefinitionFromTemplate(val template: KClass<out Any>, val
|
|||||||
val annFQN = annClassToWrapper.first.qualifiedName
|
val annFQN = annClassToWrapper.first.qualifiedName
|
||||||
if (definitionData.acceptedAnnotations.any { it.qualifiedName == annFQN }) annClassToWrapper.second else null
|
if (definitionData.acceptedAnnotations.any { it.qualifiedName == annFQN }) annClassToWrapper.second else null
|
||||||
}
|
}
|
||||||
val fileDeps = definitionData.resolver?.resolve(getFile(file), supportedAnnotations, environment, previousDependencies)
|
val fileDeps = definitionData.resolver?.resolve(BasicScriptContents(file, supportedAnnotations), environment, previousDependencies)
|
||||||
return fileDeps
|
return fileDeps
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,6 +193,12 @@ data class KotlinScriptDefinitionFromTemplate(val template: KClass<out Any>, val
|
|||||||
?: throw java.lang.IllegalArgumentException("Unable to load PSI from ${file.canonicalPath}")
|
?: throw java.lang.IllegalArgumentException("Unable to load PSI from ${file.canonicalPath}")
|
||||||
return getAnnotationEntriesFromPsiFile(psiFile)
|
return getAnnotationEntriesFromPsiFile(psiFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BasicScriptContents<out TF>(val myFile: TF, override val annotations: Iterable<Annotation>) : ScriptContents {
|
||||||
|
override val file: File? get() = getFile(myFile)
|
||||||
|
override val contents: CharSequence? get() = getFileContents(myFile)
|
||||||
|
override val contentsStream: InputStream? get() = getFileContentsStream(myFile)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InvalidScriptResolverAnnotation(val name: String, val params: Iterable<Any?>, val error: Exception? = null) : Annotation
|
class InvalidScriptResolverAnnotation(val name: String, val params: Iterable<Any?>, val error: Exception? = null) : Annotation
|
||||||
|
|||||||
@@ -25,16 +25,18 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
|
import java.util.concurrent.Future
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
abstract class BaseScriptDefinition (val extension: String, val cp: List<File>? = null) : KotlinScriptDefinition {
|
abstract class BaseScriptDefinition (val extension: String, val cp: List<File>? = null) : KotlinScriptDefinition {
|
||||||
override val name = "Test Kotlin Script"
|
override val name = "Test Kotlin Script"
|
||||||
override fun <TF> isScript(file: TF): Boolean = getFileName(file).endsWith(extension)
|
override fun <TF> isScript(file: TF): Boolean = getFileName(file).endsWith(extension)
|
||||||
override fun getScriptName(script: KtScript): Name = ScriptNameUtil.fileNameWithExtensionStripped(script, extension)
|
override fun getScriptName(script: KtScript): Name = ScriptNameUtil.fileNameWithExtensionStripped(script, extension)
|
||||||
override fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? =
|
override fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): Future<KotlinScriptExternalDependencies>? =
|
||||||
object : KotlinScriptExternalDependencies {
|
makeNullableFakeFuture(
|
||||||
override val classpath: Iterable<File> = cp ?: (classpathFromProperty() + classpathFromClassloader(BaseScriptDefinition::class.java.classLoader)).distinct()
|
object : KotlinScriptExternalDependencies {
|
||||||
}
|
override val classpath: Iterable<File> = cp ?: (classpathFromProperty() + classpathFromClassloader(BaseScriptDefinition::class.java.classLoader)).distinct()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
open class SimpleParamsWithClasspathTestScriptDefinition(extension: String, val parameters: List<ScriptParameter>, classpath: List<File>? = null, val extraDependencies: KotlinScriptExternalDependencies? = null)
|
open class SimpleParamsWithClasspathTestScriptDefinition(extension: String, val parameters: List<ScriptParameter>, classpath: List<File>? = null, val extraDependencies: KotlinScriptExternalDependencies? = null)
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.junit.Assert
|
|||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
|
import java.util.concurrent.Future
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
// TODO: the contetnts of this file should go into ScriptTest.kt and replace appropriate xml-based functionality,
|
// TODO: the contetnts of this file should go into ScriptTest.kt and replace appropriate xml-based functionality,
|
||||||
@@ -118,28 +119,27 @@ class ScriptTest2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestKotlinScriptDependenciesResolver : AnnotationBasedScriptDependenciesResolver {
|
class TestKotlinScriptDependenciesResolver : ScriptDependenciesResolverEx {
|
||||||
|
|
||||||
private val kotlinPaths by lazy { PathUtil.getKotlinPathsForCompiler() }
|
private val kotlinPaths by lazy { PathUtil.getKotlinPathsForCompiler() }
|
||||||
|
|
||||||
@AcceptedAnnotations(DependsOn::class)
|
@AcceptedAnnotations(DependsOn::class)
|
||||||
override fun resolve(scriptFile: File?,
|
override fun resolve(script: ScriptContents,
|
||||||
annotations: Iterable<Annotation>,
|
|
||||||
environment: Map<String, Any?>?,
|
environment: Map<String, Any?>?,
|
||||||
previousDependencies: KotlinScriptExternalDependencies?
|
previousDependencies: KotlinScriptExternalDependencies?
|
||||||
): KotlinScriptExternalDependencies?
|
): Future<KotlinScriptExternalDependencies>?
|
||||||
{
|
{
|
||||||
val cp = annotations.flatMap {
|
val cp = script.annotations.flatMap {
|
||||||
when (it) {
|
when (it) {
|
||||||
is DependsOn -> listOf(if (it.path == "@{runtime}") kotlinPaths.runtimePath else File(it.path))
|
is DependsOn -> listOf(if (it.path == "@{runtime}") kotlinPaths.runtimePath else File(it.path))
|
||||||
is InvalidScriptResolverAnnotation -> throw Exception("Invalid annotation ${it.name}", it.error)
|
is InvalidScriptResolverAnnotation -> throw Exception("Invalid annotation ${it.name}", it.error)
|
||||||
else -> throw Exception("Unknown annotation ${it.javaClass}")
|
else -> throw Exception("Unknown annotation ${it.javaClass}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return object : KotlinScriptExternalDependencies {
|
return makeNullableFakeFuture(object : KotlinScriptExternalDependencies {
|
||||||
override val classpath: Iterable<File> = classpathFromClassloader() + cp
|
override val classpath: Iterable<File> = classpathFromClassloader() + cp
|
||||||
override val imports: Iterable<String> = listOf("org.jetbrains.kotlin.scripts.DependsOn")
|
override val imports: Iterable<String> = listOf("org.jetbrains.kotlin.scripts.DependsOn")
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun classpathFromClassloader(): List<File> =
|
private fun classpathFromClassloader(): List<File> =
|
||||||
|
|||||||
Reference in New Issue
Block a user