diff --git a/libraries/scripting/common/src/kotlin/script/experimental/annotations/scriptAnnotations.kt b/libraries/scripting/common/src/kotlin/script/experimental/annotations/scriptAnnotations.kt
index 2ea2a778940..c6c2abb56ef 100644
--- a/libraries/scripting/common/src/kotlin/script/experimental/annotations/scriptAnnotations.kt
+++ b/libraries/scripting/common/src/kotlin/script/experimental/annotations/scriptAnnotations.kt
@@ -10,6 +10,35 @@ package kotlin.script.experimental.annotations
import kotlin.reflect.KClass
import kotlin.script.experimental.api.ScriptCompilationConfiguration
+/**
+ * The annotation for declaring a script definition (template)
+ * A class marked with this annotation is considered a script definition and could be used in script definitions discovery or
+ * referenced explicitly by FQName for compiler or IDE. The compilation configuration is constructed from the annotated class
+ * (it is used as a compiled script super class) and annotation parameters.
+ *
+ * It is important to specify [fileExtension] property via the parameter for
+ * optimal discovery and definitions loading performance.
+ *
+ * @param displayName script definition display name, stored as {@link ScriptCompilationConfigurationKeys#displayName},
+ * default - "Kotlin script"
+ * @param fileExtension distinct filename extension for the script type being defined, stored in the configuration
+ * as {@link ScriptCompilationConfigurationKeys#fileExtension},
+ * default - "kts"
+ * @param compilationConfiguration an object or a class with default constructor containing initial script compilation configuration
+ * default - {@link ScriptCompilationConfiguration#Default}
+ *
+ * Simple usage example:
+ *
+ * {@code
+ * object MyScriptConfiguration : ScriptCompilationConfiguration({
+ * defaultImports("java.io.File")
+ * })
+ *
+ * @KotlinScript(fileExtension("myscript.kts"))
+ * abstract class MyScriptBaseClass
+ * }
+ *
+ */
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class KotlinScript(
diff --git a/libraries/scripting/common/src/kotlin/script/experimental/api/errorHandling.kt b/libraries/scripting/common/src/kotlin/script/experimental/api/errorHandling.kt
index 3bf2ea3479a..f00d7aae3bb 100644
--- a/libraries/scripting/common/src/kotlin/script/experimental/api/errorHandling.kt
+++ b/libraries/scripting/common/src/kotlin/script/experimental/api/errorHandling.kt
@@ -7,23 +7,46 @@
package kotlin.script.experimental.api
+/**
+ * The single script diagnostic report
+ * @param message diagnostic message
+ * @param severity diagnostic severity ({@link ScriptDiagnostic#Severity})
+ * @param location optional source location for the diagnostic
+ * @param exception optional exception caused the diagnostic
+ */
data class ScriptDiagnostic(
val message: String,
val severity: Severity = Severity.ERROR,
val location: SourceCode.Location? = null,
val exception: Throwable? = null
) {
+ /**
+ * The diagnostic severity
+ */
enum class Severity { FATAL, ERROR, WARNING, INFO, DEBUG }
}
+/**
+ * The result wrapper with diagnostics container
+ */
sealed class ResultWithDiagnostics {
+ /**
+ * The diagnostic reports container
+ */
abstract val reports: List
+ /**
+ * The successful [value] result with optional [reports] with diagnostics
+ */
data class Success(
val value: R,
override val reports: List = listOf()
) : ResultWithDiagnostics()
+ /**
+ * The class representing the failure result
+ * @param reports diagnostics associated with the failure
+ */
data class Failure(
override val reports: List
) : ResultWithDiagnostics() {
@@ -31,14 +54,22 @@ sealed class ResultWithDiagnostics {
}
}
-// call chaining
-
+/**
+ * Chains actions on successful result:
+ * If receiver is success - executes [body] and merge diagnostic reports
+ * otherwise returns the failure as is
+ */
suspend fun ResultWithDiagnostics.onSuccess(body: suspend (R1) -> ResultWithDiagnostics): ResultWithDiagnostics =
when (this) {
is ResultWithDiagnostics.Success -> this.reports + body(this.value)
is ResultWithDiagnostics.Failure -> this
}
+/**
+ * Chains actions on failure:
+ * If receiver is failure - executed [body]
+ * otherwise returns the receiver as is
+ */
suspend fun ResultWithDiagnostics.onFailure(body: suspend (ResultWithDiagnostics) -> Unit): ResultWithDiagnostics {
if (this is ResultWithDiagnostics.Failure) {
body(this)
@@ -46,22 +77,35 @@ suspend fun ResultWithDiagnostics.onFailure(body: suspend (ResultWithDiag
return this
}
-operator fun List.plus(res: ResultWithDiagnostics): ResultWithDiagnostics = when (res) {
- is ResultWithDiagnostics.Success -> ResultWithDiagnostics.Success(res.value, this + res.reports)
- is ResultWithDiagnostics.Failure -> ResultWithDiagnostics.Failure(this + res.reports)
+/**
+ * Merges diagnostics report with the [result] wrapper
+ */
+operator fun List.plus(result: ResultWithDiagnostics): ResultWithDiagnostics = when (result) {
+ is ResultWithDiagnostics.Success -> ResultWithDiagnostics.Success(result.value, this + result.reports)
+ is ResultWithDiagnostics.Failure -> ResultWithDiagnostics.Failure(this + result.reports)
}
-// results creation
-
+/**
+ * Converts the receiver value to the Success result wrapper with optional diagnostic [reports]
+ */
fun R.asSuccess(reports: List = listOf()): ResultWithDiagnostics.Success =
ResultWithDiagnostics.Success(this, reports)
+/**
+ * Converts the receiver Throwable to the Failure results wrapper with optional [message] and [location]
+ */
fun Throwable.asDiagnostics(customMessage: String? = null, location: SourceCode.Location? = null): ScriptDiagnostic =
ScriptDiagnostic(customMessage ?: message ?: "$this", ScriptDiagnostic.Severity.ERROR, location, this)
+/**
+ * Converts the receiver String to error diagnostic report with optional [location]
+ */
fun String.asErrorDiagnostics(location: SourceCode.Location? = null): ScriptDiagnostic =
ScriptDiagnostic(this, ScriptDiagnostic.Severity.ERROR, location)
+/**
+ * Extracts the result value from the receiver wrapper or null if receiver represents a Failure
+ */
fun ResultWithDiagnostics.resultOrNull(): R? = when (this) {
is ResultWithDiagnostics.Success -> value
else -> null
diff --git a/libraries/scripting/common/src/kotlin/script/experimental/api/kotlinType.kt b/libraries/scripting/common/src/kotlin/script/experimental/api/kotlinType.kt
index bf20848496d..6f889a392d7 100644
--- a/libraries/scripting/common/src/kotlin/script/experimental/api/kotlinType.kt
+++ b/libraries/scripting/common/src/kotlin/script/experimental/api/kotlinType.kt
@@ -10,7 +10,7 @@ import kotlin.reflect.KClass
import kotlin.reflect.KType
/**
- * A Kotlin type representation for using in the scripting API
+ * The Kotlin type representation for using in the scripting API
*/
class KotlinType private constructor(
val typeName: String,
diff --git a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptCompilation.kt b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptCompilation.kt
index 5e72e3fa7cf..99d59f7e7f4 100644
--- a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptCompilation.kt
+++ b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptCompilation.kt
@@ -13,6 +13,10 @@ import kotlin.script.experimental.util.PropertiesCollection
interface ScriptCompilationConfigurationKeys
+/**
+ * The container for script compilation configuration
+ * For usages see {@link KotlinScript} and actual code examples
+ */
open class ScriptCompilationConfiguration(baseConfigurations: Iterable, body: Builder.() -> Unit) :
PropertiesCollection(Builder(baseConfigurations).apply(body).data) {
@@ -31,78 +35,142 @@ open class ScriptCompilationConfiguration(baseConfigurations: Iterable("Kotlin script") // Name of the script type
+/**
+ * The script type display name
+ */
+val ScriptCompilationConfigurationKeys.displayName by PropertiesCollection.key("Kotlin script")
-val ScriptCompilationConfigurationKeys.fileExtension by PropertiesCollection.key("kts") // file extension
+/**
+ * The script filename extension
+ */
+val ScriptCompilationConfigurationKeys.fileExtension by PropertiesCollection.key("kts")
+/**
+ * The superclass for target script class
+ */
val ScriptCompilationConfigurationKeys.baseClass by PropertiesCollection.key() // script base class
-val ScriptCompilationConfigurationKeys.scriptBodyTarget by PropertiesCollection.key(ScriptBodyTarget.Constructor)
-
+/**
+ * The list of classes that will be used as implicit receivers in the script body, as if the whole body is wrapped with "with" calls:
+ *
+ * {@code
+ * with (receiver1) {
+ * ...
+ * with (receiverN) {
+ * // script body
+ * }
+ * }
+ * }
+ *
+ *
+ * Note: the actual receivers values should be passed to the constructor of the generated script class
+ */
val ScriptCompilationConfigurationKeys.implicitReceivers by PropertiesCollection.key>() // in the order from outer to inner scope
+/**
+ * The map of names to the types
+ */
val ScriptCompilationConfigurationKeys.providedProperties by PropertiesCollection.key