Core interfaces and data structures for Kotlin script compilation, evaluation, and IDE integration
—
Type representation and handling for Kotlin types within the scripting system. Provides utilities for working with Kotlin type information in a scripting context, including type creation, nullability handling, and type conversions.
Primary class for representing Kotlin types with support for nullability and class-based type creation.
/**
* Represents a Kotlin type within the scripting system
*/
class KotlinType private constructor(
/** String representation of the type name */
val typeName: String,
/** Source KClass if created from a class (marked as @Transient) */
@Transient val fromClass: KClass<*>?,
/** Whether this type is nullable */
val isNullable: Boolean
) : Serializable {
/**
* Constructs KotlinType from fully-qualified type name
* @param qualifiedTypeName Dot-separated type name (e.g. "org.acme.Outer.Inner")
* @param isNullable Whether the type should be nullable
*/
@JvmOverloads
constructor(qualifiedTypeName: String, isNullable: Boolean = false) :
this(qualifiedTypeName.removeSuffix("?"), null, isNullable = isNullable || qualifiedTypeName.endsWith('?'))
/**
* Constructs KotlinType from reflected KClass
* @param kclass The Kotlin class to create type from
* @param isNullable Whether the type should be nullable
*/
@JvmOverloads
constructor(kclass: KClass<*>, isNullable: Boolean = false) :
this(kclass.qualifiedName ?: error("Cannot use class $kclass as a KotlinType"), kclass, isNullable)
/**
* Constructs KotlinType from reflected KType
* @param type The Kotlin type to convert
*/
constructor(type: KType) : this(type.classifier as KClass<*>, type.isMarkedNullable)
/**
* Create a new KotlinType with different nullability
* @param isNullable Whether the new type should be nullable
* @return New KotlinType with specified nullability
*/
fun withNullability(isNullable: Boolean): KotlinType
override fun toString(): String
override fun equals(other: Any?): Boolean
override fun hashCode(): Int
}Convenient functions and extensions for creating KotlinType instances.
/**
* Create KotlinType from reified type parameter
*/
inline fun <reified T> kotlinType(isNullable: Boolean = false): KotlinType {
return KotlinType.from(T::class, isNullable)
}
/**
* Extension function to convert KClass to KotlinType
*/
fun KClass<*>.toKotlinType(isNullable: Boolean = false): KotlinType {
return KotlinType.from(this, isNullable)
}
/**
* Extension function to convert KType to KotlinType
*/
fun KType.toKotlinType(): KotlinType {
return KotlinType.from(this)
}Usage Examples:
import kotlin.script.experimental.api.*
import kotlin.reflect.full.*
// Create types from classes
val stringType = KotlinType(String::class)
val nullableStringType = KotlinType(String::class, isNullable = true)
val intType = KotlinType(Int::class)
val listType = KotlinType(List::class)
// Create types from type names
val stringTypeFromName = KotlinType("kotlin.String")
val nullableIntFromName = KotlinType("kotlin.Int", isNullable = true)
// Create types from KType
val functionType = KotlinType(typeOf<(String) -> Int>())
val suspendFunctionType = KotlinType(typeOf<suspend (String) -> Int>())
// Work with nullability
val originalType = KotlinType(String::class, isNullable = false)
val nullableVersion = originalType.withNullability(true)
val nonNullableVersion = nullableVersion.withNullability(false)
println("Original: $originalType") // String
println("Nullable: $nullableVersion") // String?
println("Non-nullable: $nonNullableVersion") // String
// Check properties
println("Is nullable: ${nullableVersion.isNullable}") // true
println("Type name: ${originalType.typeName}") // kotlin.String
println("From class: ${originalType.fromClass}") // class kotlin.String// Using KotlinType in script compilation configuration
val compilationConfig = ScriptCompilationConfiguration {
// Set base class for scripts
baseClass(KotlinType(Any::class))
// Add implicit receivers
implicitReceivers(
KotlinType(File::class),
KotlinType(Properties::class)
)
// Provide properties with specific types
providedProperties(mapOf(
"logger" to KotlinType(Logger::class),
"config" to KotlinType(Configuration::class),
"args" to KotlinType(Array<String>::class),
"optionalValue" to KotlinType(String::class, isNullable = true)
))
// Add dependencies with type information
dependencies.append(JvmDependency("org.slf4j:slf4j-api:1.7.36"))
}
// Using KotlinType in script evaluation configuration
val evaluationConfig = ScriptEvaluationConfiguration {
// Provide implicit receivers as actual objects
implicitReceivers(
File(System.getProperty("user.dir")),
System.getProperties()
)
// Context variables with type safety
contextVariables(mapOf(
"database" to getDatabaseConnection(), // Type inferred
"timeout" to Duration.ofSeconds(30) // Type inferred
))
}// Complex type creation and manipulation
class TypeManager {
private val typeCache = mutableMapOf<String, KotlinType>()
fun getOrCreateType(className: String, isNullable: Boolean = false): KotlinType? {
val cacheKey = "$className:$isNullable"
return typeCache.getOrPut(cacheKey) {
try {
val kClass = Class.forName(className).kotlin
KotlinType.from(kClass, isNullable)
} catch (e: ClassNotFoundException) {
return null
}
}
}
fun createGenericType(baseClassName: String, typeArguments: List<KotlinType>): KotlinType? {
// This would require more complex type construction
// For demonstration purposes, simplified
return getOrCreateType(baseClassName)
}
}
// Using type manager
val typeManager = TypeManager()
val stringType = typeManager.getOrCreateType("kotlin.String")
val nullableIntType = typeManager.getOrCreateType("kotlin.Int", isNullable = true)// Type validation utilities
object TypeValidator {
fun isAssignableFrom(target: KotlinType, source: KotlinType): Boolean {
// Simplified validation logic
if (target.typeName == source.typeName) {
return !target.isNullable || source.isNullable
}
// Check if source can be assigned to target
val targetClass = target.fromClass
val sourceClass = source.fromClass
return if (targetClass != null && sourceClass != null) {
targetClass.isInstance(sourceClass) || sourceClass.isSubclassOf(targetClass)
} else {
false
}
}
fun canBeNull(type: KotlinType): Boolean = type.isNullable
fun makeNullable(type: KotlinType): KotlinType = type.withNullability(true)
fun makeNonNull(type: KotlinType): KotlinType = type.withNullability(false)
}
// Type conversion utilities
object TypeConverter {
fun convertValue(value: Any?, targetType: KotlinType): Any? {
if (value == null) {
return if (targetType.isNullable) null
else throw IllegalArgumentException("Cannot assign null to non-nullable type")
}
// Simplified conversion logic
return when (targetType.typeName) {
"kotlin.String" -> value.toString()
"kotlin.Int" -> when (value) {
is Number -> value.toInt()
is String -> value.toIntOrNull()
else -> null
}
"kotlin.Boolean" -> when (value) {
is Boolean -> value
is String -> value.toBooleanStrictOrNull()
else -> null
}
else -> value
}
}
}// Working with collection types
fun createCollectionTypes(): Map<String, KotlinType> {
return mapOf(
"stringList" to kotlinType<List<String>>(),
"nullableStringList" to kotlinType<List<String?>>(),
"stringToIntMap" to kotlinType<Map<String, Int>>(),
"mutableIntSet" to kotlinType<MutableSet<Int>>(),
"arrayOfStrings" to kotlinType<Array<String>>(),
"intArray" to kotlinType<IntArray>()
)
}
// Function type handling
fun createFunctionTypes(): Map<String, KotlinType> {
return mapOf(
"stringTransform" to typeOf<(String) -> String>().toKotlinType(),
"suspendStringTransform" to typeOf<suspend (String) -> String>().toKotlinType(),
"predicate" to typeOf<(String) -> Boolean>().toKotlinType(),
"callback" to typeOf<(Result<String>) -> Unit>().toKotlinType(),
"supplier" to typeOf<() -> String>().toKotlinType()
)
}
// Using collection and function types in configuration
val advancedConfig = ScriptCompilationConfiguration {
providedProperties(mapOf(
"items" to kotlinType<List<String>>(),
"processor" to typeOf<(String) -> String>().toKotlinType(),
"validator" to typeOf<(String) -> Boolean>().toKotlinType(),
"results" to kotlinType<MutableMap<String, Any?>>(),
"callback" to typeOf<suspend (Result<Any>) -> Unit>().toKotlinType()
))
}// Type reflection utilities
object TypeReflectionUtils {
fun getTypeInfo(type: KotlinType): TypeInfo {
val kClass = type.fromClass
return TypeInfo(
typeName = type.typeName,
isNullable = type.isNullable,
isInterface = kClass?.isData == true,
isData = kClass?.isData == true,
isSealed = kClass?.isSealed == true,
constructors = kClass?.constructors?.size ?: 0,
properties = kClass?.memberProperties?.size ?: 0,
functions = kClass?.memberFunctions?.size ?: 0
)
}
fun validateTypeUsage(type: KotlinType, value: Any?): ValidationResult {
if (value == null) {
return if (type.isNullable) {
ValidationResult.Success
} else {
ValidationResult.Error("Null value for non-nullable type ${type.typeName}")
}
}
val valueClass = value::class
val targetClass = type.fromClass
return if (targetClass != null && targetClass.isInstance(value)) {
ValidationResult.Success
} else {
ValidationResult.Error("Value of type ${valueClass.simpleName} cannot be assigned to ${type.typeName}")
}
}
}
data class TypeInfo(
val typeName: String,
val isNullable: Boolean,
val isInterface: Boolean,
val isData: Boolean,
val isSealed: Boolean,
val constructors: Int,
val properties: Int,
val functions: Int
)
sealed class ValidationResult {
object Success : ValidationResult()
data class Error(val message: String) : ValidationResult()
}Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-scripting-common