AbstractScriptConfigurationTest: rewrite script template setup

Allow simpler setup of common scenarios
Do not require to define DependenciesResolver for every test
Drop redundant template files
This commit is contained in:
Pavel V. Talanov
2017-09-06 18:04:10 +03:00
parent d7149a4083
commit 53144def10
21 changed files with 114 additions and 280 deletions
@@ -5,3 +5,5 @@ val g = listOf("a", "b", "c")
val time = measureNanoTime { val time = measureNanoTime {
println("text") println("text")
} }
// DEPENDENCIES: classpath:runtime-classes; imports:kotlin.system.*
@@ -1,25 +0,0 @@
package custom.scriptDefinition
import kotlin.script.dependencies.*
import kotlin.script.templates.*
import java.io.File
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future
class TestDependenciesResolver : ScriptDependenciesResolver {
override fun resolve(
script: ScriptContents,
environment: Map<String, Any?>?,
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, previousDependencies: KotlinScriptExternalDependencies?
): Future<KotlinScriptExternalDependencies?> {
return CompletableFuture.completedFuture(
object : KotlinScriptExternalDependencies {
override val classpath: Iterable<File> = listOf(environment?.get("runtime-classes") as File)
override val imports: Iterable<String> = listOf("kotlin.system.*")
})
}
}
@ScriptTemplateDefinition(TestDependenciesResolver::class, scriptFilePattern = "script.kts")
class Template
@@ -6,3 +6,4 @@ doStuff(c1, c2)
doStuff(c1, <error>3</error>) doStuff(c1, <error>3</error>)
// DEPENDENCIES: classpath:lib-classes; imports:custom.library.*
@@ -1,28 +0,0 @@
package custom.scriptDefinition
import kotlin.script.dependencies.*
import kotlin.script.templates.*
import java.io.File
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future
class TestDependenciesResolver : ScriptDependenciesResolver {
override fun resolve(
script: ScriptContents,
environment: Map<String, Any?>?,
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, previousDependencies: KotlinScriptExternalDependencies?
): Future<KotlinScriptExternalDependencies?> {
return CompletableFuture.completedFuture(
object : KotlinScriptExternalDependencies {
override val classpath: Iterable<File> = listOf(
environment?.get("lib-classes") as File
)
override val imports: Iterable<String> = listOf("custom.library.*")
})
}
}
@ScriptTemplateDefinition(TestDependenciesResolver::class, scriptFilePattern = "script.kts")
class Template
@@ -6,4 +6,6 @@ fun f(
<warning>i</warning>: JavaInterface.F.I <warning>i</warning>: JavaInterface.F.I
) { ) {
} }
// DEPENDENCIES: classpath:lib-classes; imports:custom.library.*
@@ -1,28 +0,0 @@
package custom.scriptDefinition
import kotlin.script.dependencies.*
import kotlin.script.templates.*
import java.io.File
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future
class TestDependenciesResolver : ScriptDependenciesResolver {
override fun resolve(
script: ScriptContents,
environment: Map<String, Any?>?,
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, previousDependencies: KotlinScriptExternalDependencies?
): Future<KotlinScriptExternalDependencies?> {
return CompletableFuture.completedFuture(
object : KotlinScriptExternalDependencies {
override val classpath: Iterable<File> = listOf(
environment?.get("lib-classes") as File
)
override val imports: Iterable<String> = listOf("custom.library.*")
})
}
}
@ScriptTemplateDefinition(TestDependenciesResolver::class, scriptFilePattern = "script.kts")
class Template
@@ -4,4 +4,6 @@ val g = listOf("a", "b", "c")
val time = <error>measureNanoTime</error> { val time = <error>measureNanoTime</error> {
println("text") println("text")
} }
// DEPENDENCIES: classpath:runtime-classes
@@ -1,24 +0,0 @@
package custom.scriptDefinition
import kotlin.script.dependencies.*
import kotlin.script.templates.*
import java.io.File
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future
class TestDependenciesResolver : ScriptDependenciesResolver {
override fun resolve(
script: ScriptContents,
environment: Map<String, Any?>?,
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, previousDependencies: KotlinScriptExternalDependencies?
): Future<KotlinScriptExternalDependencies?> {
return CompletableFuture.completedFuture(
object : KotlinScriptExternalDependencies {
override val classpath: Iterable<File> = listOf(environment?.get("runtime-classes") as File)
})
}
}
@ScriptTemplateDefinition(TestDependenciesResolver::class, scriptFilePattern = "script.kts")
class Template
@@ -1,3 +1,6 @@
test.Utils.fo<caret>o("asd") test.Utils.fo<caret>o("asd")
// DEPENDENCIES: classpath:lib-classes
// REF: (in test.Utils).foo(String) // REF: (in test.Utils).foo(String)
// FILE: test/Utils.class // FILE: test/Utils.class
@@ -1,24 +0,0 @@
package custom.scriptDefinition
import kotlin.script.dependencies.*
import kotlin.script.templates.*
import java.io.File
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future
class TestDependenciesResolver : ScriptDependenciesResolver {
override fun resolve(
script: ScriptContents,
environment: Map<String, Any?>?,
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, previousDependencies: KotlinScriptExternalDependencies?
): Future<KotlinScriptExternalDependencies?> {
return CompletableFuture.completedFuture(
object : KotlinScriptExternalDependencies {
override val classpath: Iterable<File> = listOf(environment?.get("lib-classes") as File)
})
}
}
@ScriptTemplateDefinition(TestDependenciesResolver::class, scriptFilePattern = "script.kts")
class Template
@@ -1,3 +1,6 @@
test.Utils.fo<caret>o("asd") test.Utils.fo<caret>o("asd")
// DEPENDENCIES: classpath:lib-classes; sources:lib-source
// REF: (in test.Utils).foo(String) // REF: (in test.Utils).foo(String)
// FILE: test/Utils.java // FILE: test/Utils.java
@@ -1,25 +0,0 @@
package custom.scriptDefinition
import kotlin.script.dependencies.*
import kotlin.script.templates.*
import java.io.File
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future
class TestDependenciesResolver : ScriptDependenciesResolver {
override fun resolve(
script: ScriptContents,
environment: Map<String, Any?>?,
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, previousDependencies: KotlinScriptExternalDependencies?
): Future<KotlinScriptExternalDependencies?> {
return CompletableFuture.completedFuture(
object : KotlinScriptExternalDependencies {
override val classpath: Iterable<File> = listOf(environment?.get("lib-classes") as File)
override val sources: Iterable<File> = listOf(environment?.get("lib-source") as File)
})
}
}
@ScriptTemplateDefinition(TestDependenciesResolver::class, scriptFilePattern = "script.kts")
class Template
@@ -1,3 +1,6 @@
test.KObject.<caret>foo() test.KObject.<caret>foo()
// DEPENDENCIES: classpath:lib-classes
// REF: (in test.KObject).foo() // REF: (in test.KObject).foo()
// FILE: test/KObject.class // FILE: test/KObject.class
@@ -1,24 +0,0 @@
package custom.scriptDefinition
import kotlin.script.dependencies.*
import kotlin.script.templates.*
import java.io.File
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future
class TestDependenciesResolver : ScriptDependenciesResolver {
override fun resolve(
script: ScriptContents,
environment: Map<String, Any?>?,
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, previousDependencies: KotlinScriptExternalDependencies?
): Future<KotlinScriptExternalDependencies?> {
return CompletableFuture.completedFuture(
object : KotlinScriptExternalDependencies {
override val classpath: Iterable<File> = listOf(environment?.get("lib-classes") as File)
})
}
}
@ScriptTemplateDefinition(TestDependenciesResolver::class, scriptFilePattern = "script.kts")
class Template
@@ -1,3 +1,6 @@
test.KObject.<caret>foo() test.KObject.<caret>foo()
// DEPENDENCIES: classpath:lib-classes; sources:lib-source
// REF: (in test.KObject).foo() // REF: (in test.KObject).foo()
// FILE: test/custom.kt // FILE: test/custom.kt
@@ -1,25 +0,0 @@
package custom.scriptDefinition
import kotlin.script.dependencies.*
import kotlin.script.templates.*
import java.io.File
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future
class TestDependenciesResolver : ScriptDependenciesResolver {
override fun resolve(
script: ScriptContents,
environment: Map<String, Any?>?,
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, previousDependencies: KotlinScriptExternalDependencies?
): Future<KotlinScriptExternalDependencies?> {
return CompletableFuture.completedFuture(
object : KotlinScriptExternalDependencies {
override val classpath: Iterable<File> = listOf(environment?.get("lib-classes") as File)
override val sources: Iterable<File> = listOf(environment?.get("lib-source") as File)
})
}
}
@ScriptTemplateDefinition(TestDependenciesResolver::class, scriptFilePattern = "script.kts")
class Template
@@ -1,4 +1,6 @@
val g = lis<caret>tOf("a", "b", "c") val g = lis<caret>tOf("a", "b", "c")
// DEPENDENCIES: classpath:runtime-classes
// REF: (kotlin.collections).listOf(vararg T) // REF: (kotlin.collections).listOf(vararg T)
// FILE: collections/CollectionsKt.class // FILE: collections/CollectionsKt.class
@@ -1,24 +0,0 @@
package custom.scriptDefinition
import kotlin.script.dependencies.*
import kotlin.script.templates.*
import java.io.File
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future
class TestDependenciesResolver : ScriptDependenciesResolver {
override fun resolve(
script: ScriptContents,
environment: Map<String, Any?>?,
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, previousDependencies: KotlinScriptExternalDependencies?
): Future<KotlinScriptExternalDependencies?> {
return CompletableFuture.completedFuture(
object : KotlinScriptExternalDependencies {
override val classpath: Iterable<File> = listOf(environment?.get("runtime-classes") as File)
})
}
}
@ScriptTemplateDefinition(TestDependenciesResolver::class, scriptFilePattern = "script.kts")
class Template
@@ -1,4 +1,6 @@
val g = lis<caret>tOf("a", "b", "c") val g = lis<caret>tOf("a", "b", "c")
// DEPENDENCIES: classpath:runtime-classes; sources:runtime-source
// REF: (kotlin.collections).listOf(vararg T) // REF: (kotlin.collections).listOf(vararg T)
// FILE: collections/Collections.kt // FILE: collections/Collections.kt
@@ -1,25 +0,0 @@
package custom.scriptDefinition
import kotlin.script.dependencies.*
import kotlin.script.templates.*
import java.io.File
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future
class TestDependenciesResolver : ScriptDependenciesResolver {
override fun resolve(
script: ScriptContents,
environment: Map<String, Any?>?,
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, previousDependencies: KotlinScriptExternalDependencies?
): Future<KotlinScriptExternalDependencies?> {
return CompletableFuture.completedFuture(
object : KotlinScriptExternalDependencies {
override val classpath: Iterable<File> = listOf(environment?.get("runtime-classes") as File)
override val sources: Iterable<File> = listOf(environment?.get("runtime-source") as File)
})
}
}
@ScriptTemplateDefinition(TestDependenciesResolver::class, scriptFilePattern = "script.kts")
class Template
@@ -37,11 +37,18 @@ import org.jetbrains.kotlin.utils.PathUtil
import org.junit.Assert import org.junit.Assert
import java.io.File import java.io.File
import java.util.regex.Pattern import java.util.regex.Pattern
import kotlin.script.dependencies.Environment
import kotlin.script.dependencies.ScriptContents
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.experimental.dependencies.ScriptDependencies
import kotlin.script.experimental.dependencies.asSuccess
import kotlin.script.templates.ScriptTemplateDefinition
abstract class AbstractScriptConfigurationHighlightingTest : AbstractScriptConfigurationTest() { abstract class AbstractScriptConfigurationHighlightingTest : AbstractScriptConfigurationTest() {
override fun doTest(path: String) { override fun doTest(path: String) {
configureScriptEnvironment(path) registerScriptTemplateProvider(createScriptEnvironment(path))
super.doTest(setupScriptFile(path)) super.doTest(setupScriptFile(path))
} }
@@ -50,7 +57,7 @@ abstract class AbstractScriptConfigurationHighlightingTest : AbstractScriptConfi
abstract class AbstractScriptConfigurationNavigationTest : AbstractScriptConfigurationTest() { abstract class AbstractScriptConfigurationNavigationTest : AbstractScriptConfigurationTest() {
override fun doTest(path: String) { override fun doTest(path: String) {
configureScriptEnvironment(path) registerScriptTemplateProvider(createScriptEnvironment(path))
myFixture.configureFromExistingVirtualFile(setupScriptFile(path)) myFixture.configureFromExistingVirtualFile(setupScriptFile(path))
val reference = myFixture.getReferenceAtCaretPosition()!! val reference = myFixture.getReferenceAtCaretPosition()!!
@@ -69,20 +76,56 @@ abstract class AbstractScriptConfigurationNavigationTest : AbstractScriptConfigu
} }
} }
private val validKeys = setOf("sources", "classpath", "imports")
private const val useDefaultTemplate = "// DEPENDENCIES:"
private fun String.splitOrEmpty(delimeters: String) = split(delimeters).takeIf { it.size > 1 } ?: emptyList()
private val switches = listOf(
useDefaultTemplate
)
abstract class AbstractScriptConfigurationTest : AbstractPsiCheckerTest() { abstract class AbstractScriptConfigurationTest : AbstractPsiCheckerTest() {
protected fun configureScriptEnvironment(path: String) { protected fun createScriptEnvironment(path: String): Environment {
val templateOutDir = compileLibToDir( val defaultEnvironment = defaultEnvironment(path)
File("${path}template"), val env = mutableMapOf<String, Any?>()
PathUtil.kotlinPathsForDistDirectory.scriptRuntimePath.path File("${path}script.kts").forEachLine { line ->
) line.trim().takeIf { useDefaultTemplate in it }?.substringAfter(useDefaultTemplate)?.split(";")?.forEach { entry ->
val (key, values) = entry.splitOrEmpty(":").map { it.trim() }
assert(key in validKeys) { "Unexpected key: $key" }
env[key] = values.split(",").map {
val str = it.trim()
defaultEnvironment[str] ?: str
}
}
val libSrcDir = File("${path}lib") switches.forEach {
val libClasses = if (libSrcDir.isDirectory) { if (it in line) {
compileLibToDir(libSrcDir) env[it] = true
}
}
} }
else null if (env[useDefaultTemplate] == true && defaultEnvironment["template-classes"] != null) {
error("Script configuration should be defined by either '$useDefaultTemplate' clause or via template in 'template' directory")
}
env.putAll(defaultEnvironment)
return env
}
registerScriptTemplateProvider(templateOutDir, libClasses, libSrcDir) private fun defaultEnvironment(path: String): Map<String, File?> {
val templateOutDir = File("${path}template").takeIf { it.isDirectory }?.let {
compileLibToDir(it, PathUtil.kotlinPathsForDistDirectory.scriptRuntimePath.path)
}
val libSrcDir = File("${path}lib").takeIf { it.isDirectory }
val libClasses = libSrcDir?.let { compileLibToDir(it) }
return mapOf(
"runtime-classes" to ForTestCompileRuntime.runtimeJarForTests(),
"runtime-source" to File("libraries/stdlib/src"),
"lib-classes" to libClasses,
"lib-source" to libSrcDir,
"template-classes" to templateOutDir
)
} }
protected fun setupScriptFile(path: String): VirtualFile { protected fun setupScriptFile(path: String): VirtualFile {
@@ -112,17 +155,13 @@ abstract class AbstractScriptConfigurationTest : AbstractPsiCheckerTest() {
return outDir return outDir
} }
private fun registerScriptTemplateProvider(templateDir: File, libClasses: File?, libSource: File?) { protected fun registerScriptTemplateProvider(environment: Environment) {
val provider = TestScriptTemplateProvider( val provider = if (environment[useDefaultTemplate] == true) {
templateDir, FromTextTemplateProvider(environment)
mapOf( }
"runtime-classes" to ForTestCompileRuntime.runtimeJarForTests(), else {
"runtime-source" to File("libraries/stdlib/src"), CustomScriptTemplateProvider(environment)
"lib-classes" to libClasses, }
"lib-source" to libSource,
"template-classes" to templateDir
)
)
PlatformTestUtil.registerExtension( PlatformTestUtil.registerExtension(
Extensions.getArea(project), Extensions.getArea(project),
@@ -136,12 +175,36 @@ abstract class AbstractScriptConfigurationTest : AbstractPsiCheckerTest() {
override fun getProjectDescriptor() = KotlinLightProjectDescriptor.INSTANCE override fun getProjectDescriptor() = KotlinLightProjectDescriptor.INSTANCE
} }
class TestScriptTemplateProvider( class CustomScriptTemplateProvider(
compiledTemplateDir: File,
override val environment: Map<String, Any?> override val environment: Map<String, Any?>
) : ScriptTemplatesProvider { ) : ScriptTemplatesProvider {
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 templateClasspath = listOf(compiledTemplateDir) override val templateClasspath = listOfNotNull(environment["template-classes"] as? File)
} }
class FromTextTemplateProvider(
override val environment: Map<String, Any?>
) : ScriptTemplatesProvider {
override val id = "Test"
override val isValid = true
override val templateClassNames = listOf("org.jetbrains.kotlin.idea.script.Template")
override val templateClasspath get() = emptyList<File>()
}
class FromTextDependenciesResolver : AsyncDependenciesResolver {
@Suppress("UNCHECKED_CAST")
suspend override fun resolveAsync(scriptContents: ScriptContents, environment: Environment): DependenciesResolver.ResolveResult {
return ScriptDependencies(
classpath = (environment["classpath"] as? List<File>).orEmpty(),
imports = (environment["imports"] as? List<String>).orEmpty(),
sources = (environment["sources"] as? List<File>).orEmpty()
).asSuccess()
}
}
@Suppress("unused")
@ScriptTemplateDefinition(FromTextDependenciesResolver::class, scriptFilePattern = "script.kts")
class Template