From ab63d59a56b05c9d77d5785057b56e9e2761c612 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Fri, 17 Aug 2018 13:15:41 +0200 Subject: [PATCH] Refactor definition keys --- .../AbstractCustomScriptCodegenTest.kt | 22 ++++--- .../examples/jvm/resolve/maven/scriptDef.kt | 57 ++++++++----------- .../experimental/api/scriptConfiguration.kt | 43 +++++++------- .../script/experimental/api/scriptData.kt | 2 +- .../experimental/api/scriptDefinition.kt | 52 ++++++++--------- .../definitions/definitionFromAnnotation.kt | 2 +- .../experimental/util/propertiesCollection.kt | 2 +- .../jvmhost/impl/KJVMCompilerImpl.kt | 3 +- .../jvmhost/jvmScriptCompilation.kt | 17 ++---- .../jvm/impl/BridgeDependenciesResolver.kt | 8 +-- ...KotlinScriptDefinitionAdapterFromNewAPI.kt | 18 ++---- 11 files changed, 100 insertions(+), 126 deletions(-) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/AbstractCustomScriptCodegenTest.kt b/compiler/tests/org/jetbrains/kotlin/codegen/AbstractCustomScriptCodegenTest.kt index 7a7af14f1a5..f653b07ef49 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/AbstractCustomScriptCodegenTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/codegen/AbstractCustomScriptCodegenTest.kt @@ -21,8 +21,8 @@ import org.junit.Assert import java.io.File import kotlin.script.experimental.annotations.KotlinScript import kotlin.script.experimental.api.ScriptDefinition -import kotlin.script.experimental.api.contextVariables -import kotlin.script.experimental.api.scriptImplicitReceivers +import kotlin.script.experimental.api.implicitReceivers +import kotlin.script.experimental.api.providedProperties abstract class AbstractCustomScriptCodegenTest : CodegenTestCase() { private lateinit var scriptDefinitions: List @@ -121,21 +121,19 @@ abstract class AbstractCustomScriptCodegenTest : CodegenTestCase() { } } -object TestScriptWithReceiversConfiguration : ScriptDefinition { - override val properties = properties { - scriptImplicitReceivers() - } -} +object TestScriptWithReceiversConfiguration : ScriptDefinition( + { + implicitReceivers() + }) @Suppress("unused") @KotlinScript(definition = TestScriptWithReceiversConfiguration::class) abstract class TestScriptWithReceivers -object TestScriptWithSimpleEnvVarsConfiguration : ScriptDefinition { - override val properties = properties { - contextVariables("stringVar1" to String::class) - } -} +object TestScriptWithSimpleEnvVarsConfiguration : ScriptDefinition( + { + providedProperties("stringVar1" to String::class) + }) @Suppress("unused") @KotlinScript(definition = TestScriptWithSimpleEnvVarsConfiguration::class) diff --git a/libraries/examples/scripting/jvm-maven-deps/script/src/org/jetbrains/kotlin/script/examples/jvm/resolve/maven/scriptDef.kt b/libraries/examples/scripting/jvm-maven-deps/script/src/org/jetbrains/kotlin/script/examples/jvm/resolve/maven/scriptDef.kt index c36d440e5c7..9129044a7b2 100644 --- a/libraries/examples/scripting/jvm-maven-deps/script/src/org/jetbrains/kotlin/script/examples/jvm/resolve/maven/scriptDef.kt +++ b/libraries/examples/scripting/jvm-maven-deps/script/src/org/jetbrains/kotlin/script/examples/jvm/resolve/maven/scriptDef.kt @@ -40,46 +40,37 @@ object MyScriptDefinition : ScriptDefinition( // variant: dependencies(collectDependenciesFromCurrentContext(... refineConfiguration { // variant ^: dynamicConfiguration - handler(MyConfigurator()) - triggerOnAnnotations(DependsOn::class, Repository::class) + onAnnotations(DependsOn::class, Repository::class, handler = ::myConfigureOnAnnotations) // variants: onAnnotations, refineOnAnnotations (esp. for dynamicConfiguration), updateOnAnnotations // other triggers: beforeParsing, onSections } } ) -class MyConfigurator : RefineScriptCompilationConfigurationHandler { +private val resolver = FilesAndMavenResolver() - private val resolver = FilesAndMavenResolver() - - override suspend operator fun invoke( - scriptSource: ScriptSource, - scriptDefinition: ScriptDefinition, - configuration: ScriptCompileConfiguration?, - processedScriptData: ProcessedScriptData? - ): ResultWithDiagnostics { - val annotations = processedScriptData?.get(ProcessedScriptData.foundAnnotations)?.takeIf { it.isNotEmpty() } - ?: return configuration.asSuccess() - val scriptContents = object : ScriptContents { - override val annotations: Iterable = annotations - override val file: File? = null - override val text: CharSequence? = null - } - val diagnostics = arrayListOf() - fun report(severity: ScriptDependenciesResolver.ReportSeverity, message: String, position: ScriptContents.Position?) { - diagnostics.add(ScriptDiagnostic(message, mapLegacyDiagnosticSeverity(severity), mapLegacyScriptPosition(position))) - } - return try { - val newDepsFromResolver = resolver.resolve(scriptContents, emptyMap(), ::report, null).get() - ?: return configuration.asSuccess(diagnostics) - val resolvedClasspath = newDepsFromResolver.classpath.toList().takeIf { it.isNotEmpty() } - ?: return configuration.asSuccess(diagnostics) - ScriptCompileConfiguration { - dependencies(JvmDependency(resolvedClasspath)) - }.asSuccess(diagnostics) - } catch (e: Throwable) { - ResultWithDiagnostics.Failure(*diagnostics.toTypedArray(), e.asDiagnostics()) - } +fun myConfigureOnAnnotations(script: ScriptDataFacade): ResultWithDiagnostics { + val annotations = script.collectedData?.get(ScriptCollectedData.foundAnnotations)?.takeIf { it.isNotEmpty() } + ?: return script.configuration.asSuccess() + val scriptContents = object : ScriptContents { + override val annotations: Iterable = annotations + override val file: File? = null + override val text: CharSequence? = null + } + val diagnostics = arrayListOf() + fun report(severity: ScriptDependenciesResolver.ReportSeverity, message: String, position: ScriptContents.Position?) { + diagnostics.add(ScriptDiagnostic(message, mapLegacyDiagnosticSeverity(severity), mapLegacyScriptPosition(position))) + } + return try { + val newDepsFromResolver = resolver.resolve(scriptContents, emptyMap(), ::report, null).get() + ?: return script.configuration.asSuccess(diagnostics) + val resolvedClasspath = newDepsFromResolver.classpath.toList().takeIf { it.isNotEmpty() } + ?: return script.configuration.asSuccess(diagnostics) + ScriptCompileConfiguration { + dependencies(JvmDependency(resolvedClasspath)) + }.asSuccess(diagnostics) + } catch (e: Throwable) { + ResultWithDiagnostics.Failure(*diagnostics.toTypedArray(), e.asDiagnostics()) } } diff --git a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptConfiguration.kt b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptConfiguration.kt index c039670b60f..2ac1bce66f8 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptConfiguration.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptConfiguration.kt @@ -30,38 +30,43 @@ val ScriptCompileConfigurationKeys.sourceFragments by PropertiesCollection.key, Any>) : PropertiesCollection(properties) { +class ScriptCollectedData(properties: Map, Any>) : PropertiesCollection(properties) { - companion object : ProcessedScriptDataKeys + companion object : ScriptCollectedDataKeys } -val ProcessedScriptDataKeys.foundAnnotations by PropertiesCollection.key>() +val ScriptCollectedDataKeys.foundAnnotations by PropertiesCollection.key>() -val ProcessedScriptDataKeys.foundFragments by PropertiesCollection.key>() +val ScriptCollectedDataKeys.foundFragments by PropertiesCollection.key>() +class ScriptDataFacade( + val source: ScriptSource, + val definition: ScriptDefinition, + val configuration: ScriptCompileConfiguration?, + val collectedData: ScriptCollectedData? = null +) -interface RefineScriptCompilationConfigurationHandler { - suspend operator fun invoke( - scriptSource: ScriptSource, - scriptDefinition: ScriptDefinition, - configuration: ScriptCompileConfiguration?, - processedScriptData: ProcessedScriptData? = null - ): ResultWithDiagnostics -} +typealias RefineScriptCompilationConfigurationHandler = (ScriptDataFacade) -> ResultWithDiagnostics + +class RefineConfigurationOnAnnotationsData( + val annotations: List, + val handler: RefineScriptCompilationConfigurationHandler +) + +class RefineConfigurationOnSectionsData( + val sections: List, + val handler: RefineScriptCompilationConfigurationHandler +) diff --git a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptData.kt b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptData.kt index a29cb93814d..b2cfc480716 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptData.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptData.kt @@ -22,7 +22,7 @@ data class ScriptSourceNamedFragment(val name: String?, val range: ScriptSource. enum class ScriptBodyTarget { Constructor, - SingleAbstractMethod + SAMFunction } data class ResolvingRestrictionRule( diff --git a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptDefinition.kt b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptDefinition.kt index 23cbb9f1492..63d4b66c0dc 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptDefinition.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptDefinition.kt @@ -29,7 +29,7 @@ open class ScriptDefinition(baseDefinitions: Iterable, body: B } } -val ScriptDefinitionKeys.name by PropertiesCollection.key("Kotlin script") // Name of the script type +val ScriptDefinitionKeys.displayName by PropertiesCollection.key("Kotlin script") // Name of the script type val ScriptDefinitionKeys.fileExtension by PropertiesCollection.key("kts") // file extension @@ -37,31 +37,25 @@ val ScriptDefinitionKeys.baseClass by PropertiesCollection.key() // val ScriptDefinitionKeys.scriptBodyTarget by PropertiesCollection.key(ScriptBodyTarget.Constructor) -val ScriptDefinitionKeys.scriptImplicitReceivers by PropertiesCollection.key>() // in the order from outer to inner scope +val ScriptDefinitionKeys.implicitReceivers by PropertiesCollection.key>() // in the order from outer to inner scope -val ScriptDefinitionKeys.contextVariables by PropertiesCollection.key>() // external variables +val ScriptDefinitionKeys.providedProperties by PropertiesCollection.key>() // external variables val ScriptDefinitionKeys.defaultImports by PropertiesCollection.key>() -val ScriptDefinitionKeys.restrictions by PropertiesCollection.key>() - -val ScriptDefinitionKeys.importedScripts by PropertiesCollection.key>() - val ScriptDefinitionKeys.dependencies by PropertiesCollection.key>() val ScriptDefinitionKeys.generatedClassAnnotations by PropertiesCollection.key>() -val ScriptDefinitionKeys.generatedMethodAnnotations by PropertiesCollection.key>() +val ScriptDefinitionKeys.copyAnnotationsFrom by PropertiesCollection.key>() val ScriptDefinitionKeys.compilerOptions by PropertiesCollection.key>() // Q: CommonCompilerOptions instead? -val ScriptDefinitionKeys.refineConfigurationHandler by PropertiesCollection.key() // dynamic configurator +val ScriptDefinitionKeys.refineConfigurationBeforeParsing by PropertiesCollection.key() // default: false -val ScriptDefinitionKeys.refineConfigurationBeforeParsing by PropertiesCollection.key() // default: false +val ScriptDefinitionKeys.refineConfigurationOnAnnotations by PropertiesCollection.key() -val ScriptDefinitionKeys.refineConfigurationOnAnnotations by PropertiesCollection.key>() - -val ScriptDefinitionKeys.refineConfigurationOnSections by PropertiesCollection.key>() +val ScriptDefinitionKeys.refineConfigurationOnSections by PropertiesCollection.key() // DSL: @@ -70,36 +64,36 @@ val ScriptDefinition.Builder.refineConfiguration get() = RefineConfigurationBuil class RefineConfigurationBuilder : PropertiesCollection.Builder() { - fun handler(fn: RefineScriptCompilationConfigurationHandler) { - set(ScriptDefinition.refineConfigurationHandler, fn) + fun beforeParsing(handler: RefineScriptCompilationConfigurationHandler) { + set(ScriptDefinition.refineConfigurationBeforeParsing, handler) } - fun triggerBeforeParsing(value: Boolean = true) { - set(ScriptDefinition.refineConfigurationBeforeParsing, value) + fun onAnnotations(annotations: List, handler: RefineScriptCompilationConfigurationHandler) { + set(ScriptDefinition.refineConfigurationOnAnnotations, RefineConfigurationOnAnnotationsData(annotations, handler)) } - fun triggerOnAnnotations(annotations: Iterable) { - ScriptDefinition.refineConfigurationOnAnnotations.append(annotations) + fun onAnnotations(vararg annotations: KotlinType, handler: RefineScriptCompilationConfigurationHandler) { + onAnnotations(annotations.asList(), handler) } - fun triggerOnAnnotations(vararg annotations: KotlinType) { - triggerOnAnnotations(annotations.asIterable()) + inline fun onAnnotations(noinline handler: RefineScriptCompilationConfigurationHandler) { + onAnnotations(listOf(KotlinType(T::class)), handler) } - inline fun triggerOnAnnotations() { - triggerOnAnnotations(KotlinType(T::class)) + fun onAnnotations(vararg annotations: KClass, handler: RefineScriptCompilationConfigurationHandler) { + onAnnotations(annotations.map { KotlinType(it) }, handler) } - fun triggerOnAnnotations(vararg annotations: KClass) { - triggerOnAnnotations(annotations.map { KotlinType(it) }) + fun onAnnotations(annotations: Iterable>, handler: RefineScriptCompilationConfigurationHandler) { + onAnnotations(annotations.map { KotlinType(it) }, handler) } - fun triggerOnSections(sections: Iterable) { - ScriptDefinition.refineConfigurationOnSections.append(sections) + fun onSections(sections: List, handler: RefineScriptCompilationConfigurationHandler) { + set(ScriptDefinition.refineConfigurationOnSections, RefineConfigurationOnSectionsData(sections, handler)) } - fun triggerOnSections(vararg sections: String) { - ScriptDefinition.refineConfigurationOnSections.append(*sections) + fun onSections(vararg sections: String, handler: RefineScriptCompilationConfigurationHandler) { + onSections(sections.asList(), handler) } } diff --git a/libraries/scripting/common/src/kotlin/script/experimental/definitions/definitionFromAnnotation.kt b/libraries/scripting/common/src/kotlin/script/experimental/definitions/definitionFromAnnotation.kt index 0d7ee15c0b7..8dda162294a 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/definitions/definitionFromAnnotation.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/definitions/definitionFromAnnotation.kt @@ -44,7 +44,7 @@ fun createScriptDefinitionFromAnnotatedBaseClass( return ScriptDefinition { baseClass(baseClassType) fileExtension(baseClass.findAnnotation()?.extension ?: mainAnnotation.extension) - name(mainAnnotation.name) + displayName(mainAnnotation.name) include(scriptingPropsInstance(mainAnnotation.definition)) diff --git a/libraries/scripting/common/src/kotlin/script/experimental/util/propertiesCollection.kt b/libraries/scripting/common/src/kotlin/script/experimental/util/propertiesCollection.kt index b0336a4fb0a..8d9a92a2b22 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/util/propertiesCollection.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/util/propertiesCollection.kt @@ -163,7 +163,7 @@ open class PropertiesCollection(val properties: Map, Any> = emptyMap()) { @JvmName("appendToMap") fun PropertiesCollection.Key>.append(values: Iterable>) { - val newValues = get(this)?.let { it + values } ?: values + val newValues = get(this)?.let { it + values } ?: values.toMap() data[this] = newValues } diff --git a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJVMCompilerImpl.kt b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJVMCompilerImpl.kt index cb1881afac6..69160e71920 100644 --- a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJVMCompilerImpl.kt +++ b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJVMCompilerImpl.kt @@ -253,7 +253,8 @@ internal class BridgeScriptDefinition( ) { override val acceptedAnnotations = run { val cl = this::class.java.classLoader - getMergedFromChainOrNull(ScriptDefinition.refineConfigurationOnAnnotations, scriptDefinition, additionalCompilationConfiguration) + getFirstFromChainOrNull(ScriptDefinition.refineConfigurationOnAnnotations, scriptDefinition, additionalCompilationConfiguration) + ?.annotations ?.map { (cl.loadClass(it.typeName) as Class).kotlin } ?: emptyList() } diff --git a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptCompilation.kt b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptCompilation.kt index a3a2103d6e5..ec973d0ad2b 100644 --- a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptCompilation.kt +++ b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptCompilation.kt @@ -40,20 +40,13 @@ open class JvmScriptCompiler( scriptDefinition: ScriptDefinition, additionalConfiguration: ScriptCompileConfiguration? ): ResultWithDiagnostics> { - val refineConfigurationFn = scriptDefinition[ScriptDefinition.refineConfigurationHandler] + val refineConfigurationFn = scriptDefinition[ScriptDefinition.refineConfigurationBeforeParsing] val refinedConfiguration = - if (scriptDefinition[ScriptDefinition.refineConfigurationBeforeParsing] == true) { - if (refineConfigurationFn == null) { - return ResultWithDiagnostics.Failure("Non-null configurator expected".asErrorDiagnostics()) + refineConfigurationFn?.invoke(ScriptDataFacade(script, scriptDefinition, additionalConfiguration))?.let { + when (it) { + is ResultWithDiagnostics.Failure -> return it + is ResultWithDiagnostics.Success -> it.value } - refineConfigurationFn(script, scriptDefinition, additionalConfiguration).let { - when (it) { - is ResultWithDiagnostics.Failure -> return it - is ResultWithDiagnostics.Success -> it.value - } - } - } else { - null } val actualConfiguration = mergeConfigurations(additionalConfiguration, refinedConfiguration) val cached = cache.get(script, scriptDefinition, actualConfiguration) diff --git a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/impl/BridgeDependenciesResolver.kt b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/impl/BridgeDependenciesResolver.kt index cd6593a86a3..735e05771f6 100644 --- a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/impl/BridgeDependenciesResolver.kt +++ b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/impl/BridgeDependenciesResolver.kt @@ -35,18 +35,18 @@ class BridgeDependenciesResolver( return try { val diagnostics = arrayListOf() - val processedScriptData = ProcessedScriptData( + val processedScriptData = ScriptCollectedData( mapOf( - ProcessedScriptData.foundAnnotations to scriptContents.annotations + ScriptCollectedData.foundAnnotations to scriptContents.annotations ) ) - val refineFn = scriptDefinition[ScriptDefinition.refineConfigurationHandler] + val refineFn = scriptDefinition[ScriptDefinition.refineConfigurationOnAnnotations]?.handler val refinedConfiguration = if (refineFn == null) null else { val res = refineFn( - scriptContents.toScriptSource(), scriptDefinition, additionalConfiguration, processedScriptData + ScriptDataFacade(scriptContents.toScriptSource(), scriptDefinition, additionalConfiguration, processedScriptData) ) when (res) { is ResultWithDiagnostics.Failure -> diff --git a/plugins/scripting/scripting-cli/src/org/jetbrains/kotlin/scripting/compiler/plugin/KotlinScriptDefinitionAdapterFromNewAPI.kt b/plugins/scripting/scripting-cli/src/org/jetbrains/kotlin/scripting/compiler/plugin/KotlinScriptDefinitionAdapterFromNewAPI.kt index aff75740c28..99c94c8d653 100644 --- a/plugins/scripting/scripting-cli/src/org/jetbrains/kotlin/scripting/compiler/plugin/KotlinScriptDefinitionAdapterFromNewAPI.kt +++ b/plugins/scripting/scripting-cli/src/org/jetbrains/kotlin/scripting/compiler/plugin/KotlinScriptDefinitionAdapterFromNewAPI.kt @@ -36,7 +36,7 @@ abstract class KotlinScriptDefinitionAdapterFromNewAPIBase : KotlinScriptDefinit override val template: KClass<*> get() = baseClass override val name: String - get() = scriptDefinition[ScriptDefinition.name] ?: "Kotlin Script" + get() = scriptDefinition[ScriptDefinition.displayName] ?: "Kotlin Script" override val fileType: LanguageFileType = KotlinFileType.INSTANCE @@ -56,19 +56,19 @@ abstract class KotlinScriptDefinitionAdapterFromNewAPIBase : KotlinScriptDefinit } override val acceptedAnnotations: List> by lazy(LazyThreadSafetyMode.PUBLICATION) { - scriptDefinition[ScriptDefinition.refineConfigurationOnAnnotations] + scriptDefinition[ScriptDefinition.refineConfigurationOnAnnotations]?.annotations .orEmpty() .map { getScriptingClass(it) as KClass } } override val implicitReceivers: List by lazy(LazyThreadSafetyMode.PUBLICATION) { - scriptDefinition[ScriptDefinition.scriptImplicitReceivers] + scriptDefinition[ScriptDefinition.implicitReceivers] .orEmpty() .map { getScriptingClass(it).starProjectedType } } override val environmentVariables: List> by lazy(LazyThreadSafetyMode.PUBLICATION) { - scriptDefinition[ScriptDefinition.contextVariables] + scriptDefinition[ScriptDefinition.providedProperties] ?.map { (k, v) -> k to getScriptingClass(v).starProjectedType }.orEmpty() } @@ -82,14 +82,6 @@ abstract class KotlinScriptDefinitionAdapterFromNewAPIBase : KotlinScriptDefinit ScriptExpectedLocation.TestsOnly ) - override val targetClassAnnotations: List - get() = scriptDefinition[ScriptDefinition.generatedClassAnnotations] - .orEmpty() - - override val targetMethodAnnotations: List - get() = scriptDefinition[ScriptDefinition.generatedMethodAnnotations] - .orEmpty() - private val scriptingClassGetter by lazy(LazyThreadSafetyMode.PUBLICATION) { hostEnvironment[ScriptingEnvironment.getScriptingClass] ?: throw IllegalArgumentException("Expecting 'getScriptingClass' property in the scripting environment") @@ -109,7 +101,7 @@ class KotlinScriptDefinitionAdapterFromNewAPI( override val hostEnvironment: ScriptingEnvironment ) : KotlinScriptDefinitionAdapterFromNewAPIBase() { - override val name: String get() = scriptDefinition[ScriptDefinition.name] ?: super.name + override val name: String get() = scriptDefinition[ScriptDefinition.displayName] ?: super.name override val scriptFileExtensionWithDot = "." + (scriptDefinition[ScriptDefinition.fileExtension] ?: "kts")