CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-kotlin--kotlin-scripting-common

Core interfaces and data structures for Kotlin script compilation, evaluation, and IDE integration

Pending
Overview
Eval results
Files

host-integration.mddocs/

Host Integration

Host system utilities for integrating Kotlin scripting into applications with script source implementations, configuration management, and execution environments. Provides the foundation for embedding scripting capabilities in host applications.

Capabilities

BasicScriptingHost

Abstract base class providing fundamental scripting host functionality with coroutine support and script evaluation.

/**
 * Abstract base class for scripting hosts
 */
abstract class BasicScriptingHost {
    /**
     * Execute code within a coroutine context
     * @param body Suspend function to execute
     */
    open suspend fun runInCoroutineContext(body: suspend () -> Unit) = body()
    
    /**
     * Evaluate a script with compilation and evaluation configurations
     * @param script Source code to evaluate
     * @param compilationConfiguration Configuration for compilation
     * @param evaluationConfiguration Optional configuration for evaluation
     * @return Result of script evaluation
     */
    suspend fun eval(
        script: SourceCode,
        compilationConfiguration: ScriptCompilationConfiguration,
        evaluationConfiguration: ScriptEvaluationConfiguration? = null
    ): ResultWithDiagnostics<EvaluationResult>
}

ScriptingHostConfiguration

Configuration container for host-level scripting settings and services.

/**
 * Configuration for scripting host
 */
class ScriptingHostConfiguration : PropertiesCollection {
    companion object {
        val Default = ScriptingHostConfiguration()
    }
}

Script Definition System

Data structures and functions for creating script definitions from templates.

/**
 * Complete definition of a script type with compilation and evaluation configurations
 */
data class ScriptDefinition(
    val compilationConfiguration: ScriptCompilationConfiguration,
    val evaluationConfiguration: ScriptEvaluationConfiguration
)

/**
 * Create script definition from annotated template class
 * @param template Class annotated with @KotlinScript
 * @param hostConfiguration Optional host configuration
 * @return Script definition with resolved configurations
 */
fun createScriptDefinitionFromTemplate(
    template: KClass<out Any>,
    hostConfiguration: ScriptingHostConfiguration = ScriptingHostConfiguration.Default
): ScriptDefinition

/**
 * Create compilation configuration from template class
 * @param template Class annotated with @KotlinScript
 * @param hostConfiguration Optional host configuration
 * @return Resolved compilation configuration
 */
fun createCompilationConfigurationFromTemplate(
    template: KClass<out Any>,
    hostConfiguration: ScriptingHostConfiguration = ScriptingHostConfiguration.Default
): ScriptCompilationConfiguration

/**
 * Create evaluation configuration from template class
 * @param template Class annotated with @KotlinScript
 * @param hostConfiguration Optional host configuration
 * @return Resolved evaluation configuration
 */
fun createEvaluationConfigurationFromTemplate(
    template: KClass<out Any>,
    hostConfiguration: ScriptingHostConfiguration = ScriptingHostConfiguration.Default
): ScriptEvaluationConfiguration

Source Code Implementations

Ready-to-use implementations for different types of script sources.

/**
 * Abstract base class for file-based script sources
 */
abstract class FileBasedScriptSource : ExternalSourceCode {
    /** The file containing the script source */
    abstract val file: File
    
    override val text: String get() = file.readText()
    override val name: String? get() = file.name
    override val locationId: String? get() = file.absolutePath
}

/**
 * Script source backed by a file
 */
class FileScriptSource(override val file: File) : FileBasedScriptSource() {
    override val externalLocation: String? get() = file.absolutePath
}

/**
 * Script source backed by a URL
 */
class UrlScriptSource(
    private val url: URL,
    override val text: String
) : ExternalSourceCode {
    override val name: String? get() = url.file.substringAfterLast('/')
    override val locationId: String? get() = url.toString()
    override val externalLocation: String? get() = url.toString()
}

/**
 * Script source backed by a string
 */
class StringScriptSource(
    override val text: String,
    override val name: String? = null
) : SourceCode {
    override val locationId: String? = name
}

Host Configuration Keys

Configuration keys for host-level scripting settings.

/**
 * Configuration keys for scripting host
 */
interface ScriptingHostConfigurationKeys {
    val jvmTarget: PropertiesCollection.Key<String>
    val getScriptingClass: PropertiesCollection.Key<GetScriptingClass>
    val configurationDependencies: PropertiesCollection.Key<List<ScriptDependency>>
}

/**
 * Interface for loading classes in the scripting environment
 */
interface GetScriptingClass {
    /**
     * Load a class by name
     * @param className Fully qualified class name
     * @return Loaded class or null if not found
     */
    operator fun invoke(className: String): KClass<*>?
}

Extension Functions

Utility extension functions for host integration.

/**
 * Convert File to script source
 */
fun File.toScriptSource(): FileScriptSource

/**
 * Convert String to script source with optional name
 */
fun String.toScriptSource(name: String? = null): StringScriptSource

/**
 * Get scripting class loader from host configuration
 */
fun ScriptingHostConfiguration.getScriptingClass(): GetScriptingClass?

Usage Examples:

import kotlin.script.experimental.host.*
import kotlin.script.experimental.api.*

// Custom scripting host implementation
class MyScriptingHost : BasicScriptingHost() {
    private val compiler: ScriptCompiler = TODO("Implementation")
    private val evaluator: ScriptEvaluator = TODO("Implementation")
    
    override suspend fun runInCoroutineContext(body: suspend () -> Unit) {
        // Custom coroutine context setup
        withContext(Dispatchers.IO) {
            body()
        }
    }
    
    suspend fun executeScript(scriptFile: File): ResultWithDiagnostics<Any?> {
        val source = scriptFile.toScriptSource()
        val compilationConfig = ScriptCompilationConfiguration {
            defaultImports("kotlin.math.*")
        }
        val evaluationConfig = ScriptEvaluationConfiguration.Default
        
        return eval(source, compilationConfig, evaluationConfig).map { result ->
            when (val returnValue = result.returnValue) {
                is ResultValue.Value -> returnValue.value
                is ResultValue.Unit -> Unit
                is ResultValue.Error -> throw returnValue.error
                is ResultValue.NotEvaluated -> null
            }
        }
    }
}

// Using the custom host
val host = MyScriptingHost()
val scriptFile = File("script.kts")

runBlocking {
    when (val result = host.executeScript(scriptFile)) {
        is ResultWithDiagnostics.Success -> {
            println("Script result: ${result.value}")
        }
        is ResultWithDiagnostics.Failure -> {
            result.reports.forEach { diagnostic ->
                println("${diagnostic.severity}: ${diagnostic.message}")
            }
        }
    }
}

Script Definition Usage

// Define a script template
@KotlinScript(
    displayName = "Data Processing Script",
    fileExtension = "data.kts",
    compilationConfiguration = DataScriptCompilationConfig::class,
    evaluationConfiguration = DataScriptEvaluationConfig::class
)
abstract class DataScript

class DataScriptCompilationConfig : ScriptCompilationConfiguration({
    defaultImports("kotlin.collections.*", "kotlin.io.*")
    dependencies.append(JvmDependency("org.apache.commons:commons-csv:1.9.0"))
})

class DataScriptEvaluationConfig : ScriptEvaluationConfiguration({
    contextVariables.put("dataDir", File("./data"))
})

// Create script definition from template
val scriptDefinition = createScriptDefinitionFromTemplate(DataScript::class)

// Use the definition
val host = MyScriptingHost()
val script = File("process-data.data.kts").toScriptSource()

val result = host.eval(
    script,
    scriptDefinition.compilationConfiguration,
    scriptDefinition.evaluationConfiguration
)

Advanced Host Configuration

// Custom class loader for scripting
class CustomScriptingClassLoader : GetScriptingClass {
    private val additionalClassPath = mutableListOf<URL>()
    
    fun addToClassPath(url: URL) {
        additionalClassPath.add(url)
    }
    
    override fun invoke(className: String): KClass<*>? {
        return try {
            val classLoader = URLClassLoader(additionalClassPath.toTypedArray())
            Class.forName(className, false, classLoader).kotlin
        } catch (e: ClassNotFoundException) {
            null
        }
    }
}

// Host configuration with custom class loader
val customClassLoader = CustomScriptingClassLoader().apply {
    addToClassPath(File("lib/custom.jar").toURI().toURL())
}

val hostConfig = ScriptingHostConfiguration {
    getScriptingClass(customClassLoader)
    jvmTarget("1.8")
    configurationDependencies(listOf(
        JvmDependency("org.jetbrains.kotlin:kotlin-scripting-jvm:1.8.0")
    ))
}

// Create configurations with custom host config
val compilationConfig = createCompilationConfigurationFromTemplate(
    DataScript::class,
    hostConfig
)

val evaluationConfig = createEvaluationConfigurationFromTemplate(
    DataScript::class,
    hostConfig
)

Script Source Utilities

// Various ways to create script sources
val fileSource = File("script.kts").toScriptSource()
val stringSource = "println(\"Hello World\")".toScriptSource("hello.kts")

// URL-based script source
val url = URL("https://example.com/script.kts")
val urlText = url.readText()
val urlSource = UrlScriptSource(url, urlText)

// Custom script source with caching
class CachedFileScriptSource(override val file: File) : FileBasedScriptSource() {
    private var cachedText: String? = null
    private var lastModified: Long = 0
    
    override val text: String
        get() {
            val currentModified = file.lastModified()
            if (cachedText == null || currentModified > lastModified) {
                cachedText = file.readText()
                lastModified = currentModified
            }
            return cachedText!!
        }
    
    override val externalLocation: String? get() = file.absolutePath
}

// Database-backed script source
class DatabaseScriptSource(
    private val scriptId: String,
    private val database: ScriptDatabase
) : ExternalSourceCode {
    override val text: String by lazy { database.getScriptContent(scriptId) }
    override val name: String? = "script_$scriptId"
    override val locationId: String? = "db:$scriptId"
    override val externalLocation: String? = "database://scripts/$scriptId"
}

Host Integration Patterns

// Plugin-based scripting system
class PluginScriptingHost : BasicScriptingHost() {
    private val plugins = mutableMapOf<String, ScriptPlugin>()
    
    fun registerPlugin(name: String, plugin: ScriptPlugin) {
        plugins[name] = plugin
    }
    
    suspend fun executeWithPlugins(script: SourceCode): ResultWithDiagnostics<Any?> {
        // Pre-execution plugin hooks
        plugins.values.forEach { it.beforeExecution(script) }
        
        val result = eval(script, getCompilationConfig(), getEvaluationConfig())
        
        // Post-execution plugin hooks
        plugins.values.forEach { it.afterExecution(script, result) }
        
        return result.map { evaluationResult ->
            when (val returnValue = evaluationResult.returnValue) {
                is ResultValue.Value -> returnValue.value
                else -> null
            }
        }
    }
}

interface ScriptPlugin {
    suspend fun beforeExecution(script: SourceCode)
    suspend fun afterExecution(script: SourceCode, result: ResultWithDiagnostics<EvaluationResult>)
}

// Service-based scripting host
class ServiceBasedScriptingHost(
    private val compiler: ScriptCompiler,
    private val evaluator: ScriptEvaluator,
    private val logger: Logger
) : BasicScriptingHost() {
    
    override suspend fun runInCoroutineContext(body: suspend () -> Unit) {
        logger.info("Starting script execution")
        try {
            withTimeout(30000) { // 30 second timeout
                body()
            }
        } catch (e: TimeoutCancellationException) {
            logger.error("Script execution timed out")
            throw e
        } finally {
            logger.info("Script execution completed")
        }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-scripting-common

docs

error-handling.md

host-integration.md

index.md

repl-system.md

script-annotations.md

script-compilation.md

script-evaluation.md

source-code.md

type-system.md

tile.json