The Kotlin compiler infrastructure providing JVM, JavaScript, and metadata compilation capabilities
—
The Kotlin compiler uses a comprehensive type-safe configuration system with hierarchical key organization and service dependency injection. This system provides fine-grained control over compilation behavior while maintaining type safety and preventing configuration errors.
Central configuration container providing type-safe access to compilation settings through strongly-typed keys.
/**
* Type-safe configuration container for compiler settings
* Uses strongly-typed keys to prevent configuration errors
*/
class CompilerConfiguration {
/**
* Set a configuration value
*
* @param key Strongly-typed configuration key
* @param value Value to set (must match key type)
*/
fun <T> put(key: CompilerConfigurationKey<T>, value: T)
/**
* Get configuration value (nullable)
*
* @param key Configuration key to retrieve
* @return Value or null if not set
*/
fun <T> get(key: CompilerConfigurationKey<T>): T?
/**
* Get configuration value (non-null)
* Throws exception if value not set
*
* @param key Configuration key to retrieve
* @return Value (never null)
* @throws IllegalStateException if key not found
*/
fun <T> getNotNull(key: CompilerConfigurationKey<T>): T
/**
* Get configuration value with default
*
* @param key Configuration key
* @param defaultValue Value to return if key not set
* @return Value or default
*/
fun <T> get(key: CompilerConfigurationKey<T>, defaultValue: T): T
/**
* Check if configuration key is set
*
* @param key Configuration key to check
* @return true if key has been set
*/
fun isSet(key: CompilerConfigurationKey<*>): Boolean
/**
* Add to list-type configuration value
*
* @param key List-type configuration key
* @param value Value to append to list
*/
fun <T> addAll(key: CompilerConfigurationKey<List<T>>, values: Collection<T>)
/**
* Create immutable copy of configuration
*
* @return Read-only copy of current configuration
*/
fun copy(): CompilerConfiguration
}Strongly-typed configuration keys organized by functional area and platform.
/**
* Strongly-typed configuration key with type safety
*
* @param T Type of value stored with this key
*/
class CompilerConfigurationKey<T> private constructor(
private val name: String
) {
companion object {
/**
* Create a new configuration key
*
* @param name Descriptive name for the key
* @return New configuration key instance
*/
fun <T> create(name: String): CompilerConfigurationKey<T>
}
override fun toString(): String = name
}Cross-platform configuration keys used by all compiler targets.
object CommonConfigurationKeys {
/** Module name for compilation output */
val MODULE_NAME: CompilerConfigurationKey<String>
/** Language version settings and feature flags */
val LANGUAGE_VERSION_SETTINGS: CompilerConfigurationKey<LanguageVersionSettings>
/** Message collector for diagnostics and warnings */
val MESSAGE_COLLECTOR_KEY: CompilerConfigurationKey<MessageCollector>
/** Metadata version for binary compatibility */
val METADATA_VERSION: CompilerConfigurationKey<BinaryVersion>
/** Use FIR (K2) frontend */
val USE_FIR: CompilerConfigurationKey<Boolean>
/** Disable inline functions */
val DISABLE_INLINE: CompilerConfigurationKey<Boolean>
/** Report output files */
val REPORT_OUTPUT_FILES: CompilerConfigurationKey<Boolean>
/** Lookup tracker for incremental compilation */
val LOOKUP_TRACKER: CompilerConfigurationKey<LookupTracker>
/** Expect/actual tracker for multiplatform */
val EXPECT_ACTUAL_TRACKER: CompilerConfigurationKey<ExpectActualTracker>
/** Allow any scripts in source roots */
val ALLOW_ANY_SCRIPTS_IN_SOURCE_ROOTS: CompilerConfigurationKey<Boolean>
/** Render diagnostic names in messages */
val RENDER_DIAGNOSTIC_INTERNAL_NAME: CompilerConfigurationKey<Boolean>
/** Parallel backend threads */
val PARALLEL_BACKEND_THREADS: CompilerConfigurationKey<Int>
/** Content roots for source files and libraries */
val CONTENT_ROOTS: CompilerConfigurationKey<List<ContentRoot>>
/** Modules for compilation */
val MODULES: CompilerConfigurationKey<List<Module>>
/** Incremental compilation components */
val INCREMENTAL_COMPILATION: CompilerConfigurationKey<IncrementalCompilationComponents>
}Command-line interface specific configuration keys.
object CLIConfigurationKeys {
/** Message collector for CLI output */
val MESSAGE_COLLECTOR_KEY: CompilerConfigurationKey<MessageCollector>
/** Metadata version override */
val METADATA_VERSION: CompilerConfigurationKey<BinaryVersion>
/** Performance manager for profiling */
val PERF_MANAGER: CompilerConfigurationKey<CommonCompilerPerformanceManager>
/** Allow Kotlin package */
val ALLOW_KOTLIN_PACKAGE: CompilerConfigurationKey<Boolean>
/** Verify bytecode */
val VERIFY_BYTECODE: CompilerConfigurationKey<Boolean>
/** Phase configuration */
val PHASE_CONFIG: CompilerConfigurationKey<PhaseConfig>
/** Intellij plugin root */
val INTELLIJ_PLUGIN_ROOT: CompilerConfigurationKey<String>
/** Flexible phase config flag */
val FLEXIBLE_PHASE_CONFIG: CompilerConfigurationKey<Boolean>
/** Original message collector */
val ORIGINAL_MESSAGE_COLLECTOR_KEY: CompilerConfigurationKey<MessageCollector>
}JVM-specific compilation configuration keys.
object JVMConfigurationKeys {
/** Output directory for .class files */
val OUTPUT_DIRECTORY: CompilerConfigurationKey<File>
/** Output JAR file */
val OUTPUT_JAR: CompilerConfigurationKey<File>
/** Include Kotlin runtime in JAR */
val INCLUDE_RUNTIME: CompilerConfigurationKey<Boolean>
/** Classpath entries */
val CLASSPATH_ROOTS: CompilerConfigurationKey<List<File>>
/** JDK home directory */
val JDK_HOME: CompilerConfigurationKey<File>
/** JVM target version */
val JVM_TARGET: CompilerConfigurationKey<JvmTarget>
/** Assert runtime calls */
val ASSERTIONS_MODE: CompilerConfigurationKey<JVMAssertionsMode>
/** Constructor call optimization */
val CONSTRUCTOR_CALL_OPTIMIZATION: CompilerConfigurationKey<Boolean>
/** Inherit multifile parts */
val INHERIT_MULTIFILE_PARTS: CompilerConfigurationKey<Boolean>
/** Use type table */
val USE_TYPE_TABLE: CompilerConfigurationKey<Boolean>
/** Java module path */
val JVM_MODULE_PATH: CompilerConfigurationKey<List<File>>
/** Add modules */
val ADD_MODULES: CompilerConfigurationKey<List<String>>
/** No JDK flag */
val NO_JDK: CompilerConfigurationKey<Boolean>
/** Additional Java modules */
val ADDITIONAL_JAVA_MODULES: CompilerConfigurationKey<List<String>>
/** Module XML file */
val MODULE_XML_FILE: CompilerConfigurationKey<File>
/** Disable standard script definition */
val DISABLE_STANDARD_SCRIPT_DEFINITION: CompilerConfigurationKey<Boolean>
/** Retain output in memory */
val RETAIN_OUTPUT_IN_MEMORY: CompilerConfigurationKey<Boolean>
/** Disable optimization */
val DISABLE_OPTIMIZATION: CompilerConfigurationKey<Boolean>
/** Emit JVM debug info */
val EMIT_JVM_DEBUG_INFO: CompilerConfigurationKey<Boolean>
/** No optimized callable references */
val NO_OPTIMIZED_CALLABLE_REFERENCES: CompilerConfigurationKey<Boolean>
/** No Kotlin nothing value exception */
val NO_KOTLIN_NOTHING_VALUE_EXCEPTION: CompilerConfigurationKey<Boolean>
/** No reset bindings */
val NO_RESET_JAR_TIMESTAMPS: CompilerConfigurationKey<Boolean>
/** No unified null checks */
val NO_UNIFIED_NULL_CHECKS: CompilerConfigurationKey<Boolean>
}JavaScript and WebAssembly specific configuration keys.
object JSConfigurationKeys {
/** Output file for generated JavaScript */
val OUTPUT_FILE: CompilerConfigurationKey<String>
/** Output directory */
val OUTPUT_DIR: CompilerConfigurationKey<File>
/** JavaScript module kind */
val MODULE_KIND: CompilerConfigurationKey<ModuleKind>
/** Generate source maps */
val SOURCE_MAP: CompilerConfigurationKey<Boolean>
/** Embed sources in source maps */
val SOURCE_MAP_EMBED_SOURCES: CompilerConfigurationKey<SourceMapEmbedSources>
/** Source map prefix */
val SOURCE_MAP_PREFIX: CompilerConfigurationKey<String>
/** Source map names policy */
val SOURCE_MAP_NAMES_POLICY: CompilerConfigurationKey<SourceMapNamesPolicy>
/** Library files */
val LIBRARIES: CompilerConfigurationKey<List<String>>
/** Transitive libraries */
val TRANSITIVE_LIBRARIES: CompilerConfigurationKey<List<String>>
/** Main call parameters */
val MAIN: CompilerConfigurationKey<String>
/** Meta info */
val META_INFO: CompilerConfigurationKey<Boolean>
/** Target platform */
val TARGET: CompilerConfigurationKey<String>
/** Friend modules */
val FRIEND_PATHS: CompilerConfigurationKey<List<String>>
/** Metadata output directory */
val METADATA_OUTPUT_DIR: CompilerConfigurationKey<File>
/** Pretty print output */
val PRETTY_PRINT: CompilerConfigurationKey<Boolean>
/** Minify output */
val MINIFY: CompilerConfigurationKey<Boolean>
/** Define platform main arguments */
val DEFINE_PLATFORM_MAIN_FUNCTION_ARGUMENTS: CompilerConfigurationKey<String>
/** Generate comments */
val GENERATE_COMMENTS: CompilerConfigurationKey<Boolean>
/** Generate region comments */
val GENERATE_REGION_COMMENTS: CompilerConfigurationKey<Boolean>
/** Generate strict mode directive */
val GENERATE_STRICT_MODE_DIRECTIVE: CompilerConfigurationKey<Boolean>
/** Optimize generated code */
val OPTIMIZE_GENERATED_JS: CompilerConfigurationKey<Boolean>
/** Use ES6 classes */
val USE_ES6_CLASSES: CompilerConfigurationKey<Boolean>
}Dependency injection container for compiler services and components.
/**
* Service container for dependency injection
* Provides type-safe service resolution
*/
class Services private constructor() {
companion object {
/** Empty services instance */
val EMPTY: Services
/**
* Create services builder
*
* @return New services builder instance
*/
fun builder(): Builder
}
/**
* Get service by type
*
* @param serviceClass Service class to retrieve
* @return Service instance or null if not registered
*/
fun <T> get(serviceClass: Class<T>): T?
/**
* Builder for services container
*/
class Builder {
/**
* Register service implementation
*
* @param serviceClass Service interface class
* @param implementation Service implementation instance
* @return Builder for chaining
*/
fun <T> register(serviceClass: Class<T>, implementation: T): Builder
/**
* Build immutable services container
*
* @return Services container with registered services
*/
fun build(): Services
}
}Language feature and version configuration.
/**
* Language version and feature settings
* Controls available language features and compatibility
*/
interface LanguageVersionSettings {
/** Current language version */
val languageVersion: LanguageVersion
/** API version for binary compatibility */
val apiVersion: ApiVersion
/** Analysis flags for compiler behavior */
val analysisFlags: Map<AnalysisFlag<*>, Any?>
/** Specific feature support */
val specificFeatures: Map<LanguageFeature, LanguageFeature.State>
/**
* Check if language feature is enabled
*
* @param feature Language feature to check
* @return true if feature is enabled or warning level
*/
fun supportsFeature(feature: LanguageFeature): Boolean
/**
* Get feature support state
*
* @param feature Language feature to check
* @return Feature state (enabled, warning, error)
*/
fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State
/**
* Check if flag is set
*
* @param flag Analysis flag to check
* @return true if flag is enabled
*/
fun <T> getFlag(flag: AnalysisFlag<T>): T
}
/**
* Language version enumeration
*/
enum class LanguageVersion(val major: Int, val minor: Int) {
KOTLIN_1_0(1, 0),
KOTLIN_1_1(1, 1),
KOTLIN_1_2(1, 2),
KOTLIN_1_3(1, 3),
KOTLIN_1_4(1, 4),
KOTLIN_1_5(1, 5),
KOTLIN_1_6(1, 6),
KOTLIN_1_7(1, 7),
KOTLIN_1_8(1, 8),
KOTLIN_1_9(1, 9),
KOTLIN_2_0(2, 0),
KOTLIN_2_1(2, 1),
KOTLIN_2_2(2, 2);
companion object {
/** Latest stable version */
val LATEST_STABLE: LanguageVersion
/** Default version for compilation */
val DEFAULT: LanguageVersion
fun fromVersionString(version: String): LanguageVersion?
}
}
/**
* API version for binary compatibility
*/
enum class ApiVersion(val version: LanguageVersion) {
KOTLIN_1_0(LanguageVersion.KOTLIN_1_0),
KOTLIN_1_1(LanguageVersion.KOTLIN_1_1),
KOTLIN_1_2(LanguageVersion.KOTLIN_1_2),
KOTLIN_1_3(LanguageVersion.KOTLIN_1_3),
KOTLIN_1_4(LanguageVersion.KOTLIN_1_4),
KOTLIN_1_5(LanguageVersion.KOTLIN_1_5),
KOTLIN_1_6(LanguageVersion.KOTLIN_1_6),
KOTLIN_1_7(LanguageVersion.KOTLIN_1_7),
KOTLIN_1_8(LanguageVersion.KOTLIN_1_8),
KOTLIN_1_9(LanguageVersion.KOTLIN_1_9),
KOTLIN_2_0(LanguageVersion.KOTLIN_2_0),
KOTLIN_2_1(LanguageVersion.KOTLIN_2_1),
KOTLIN_2_2(LanguageVersion.KOTLIN_2_2);
companion object {
/** Latest stable API version */
val LATEST_STABLE: ApiVersion
fun fromVersionString(version: String): ApiVersion?
}
}import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.config.ApiVersion
import java.io.File
// Create basic compiler configuration
val configuration = CompilerConfiguration().apply {
// Module name
put(CommonConfigurationKeys.MODULE_NAME, "my-module")
// Language version settings
put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS,
LanguageVersionSettingsImpl(
languageVersion = LanguageVersion.KOTLIN_1_9,
apiVersion = ApiVersion.KOTLIN_1_9
)
)
// JVM-specific settings
put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File("build/classes"))
put(JVMConfigurationKeys.JVM_TARGET, JvmTarget.JVM_11)
put(JVMConfigurationKeys.CLASSPATH_ROOTS, listOf(
File("lib/kotlin-stdlib.jar"),
File("lib/my-deps.jar")
))
}import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.incremental.components.LookupTracker
// Create message collector
val messageCollector = PrintingMessageCollector(
System.err,
MessageRenderer.PLAIN_FULL_PATHS,
true // verbose
)
// Build services container
val services = Services.builder()
.register(MessageCollector::class.java, messageCollector)
.register(LookupTracker::class.java, LookupTracker.DO_NOTHING)
.build()
// Configure with services
val configuration = CompilerConfiguration().apply {
put(CommonConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
put(CommonConfigurationKeys.LOOKUP_TRACKER, services.get(LookupTracker::class.java)!!)
}import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.js.config.ModuleKind
import org.jetbrains.kotlin.js.config.SourceMapEmbedSources
val jsConfiguration = CompilerConfiguration().apply {
// Output settings
put(JSConfigurationKeys.OUTPUT_FILE, "build/js/app.js")
put(JSConfigurationKeys.MODULE_KIND, ModuleKind.COMMON_JS)
// Source map configuration
put(JSConfigurationKeys.SOURCE_MAP, true)
put(JSConfigurationKeys.SOURCE_MAP_EMBED_SOURCES, SourceMapEmbedSources.ALWAYS)
put(JSConfigurationKeys.SOURCE_MAP_PREFIX, "../src/")
// Libraries
put(JSConfigurationKeys.LIBRARIES, listOf(
"lib/kotlin-stdlib-js.jar",
"lib/kotlinx-coroutines-js.jar"
))
// Code generation
put(JSConfigurationKeys.PRETTY_PRINT, false)
put(JSConfigurationKeys.MINIFY, true)
}import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.LanguageFeature
// Create language settings with specific features
val languageSettings = LanguageVersionSettingsImpl(
languageVersion = LanguageVersion.KOTLIN_1_9,
apiVersion = ApiVersion.KOTLIN_1_9,
analysisFlags = mapOf(
AnalysisFlags.skipMetadataVersionCheck to true,
AnalysisFlags.multiPlatformDoNotCheckActual to false
),
specificFeatures = mapOf(
LanguageFeature.InlineClasses to LanguageFeature.State.ENABLED,
LanguageFeature.Coroutines to LanguageFeature.State.ENABLED
)
)
configuration.put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, languageSettings)// Plugin-specific configuration keys
object MyPluginConfigurationKeys {
val ENABLE_FEATURE_X = CompilerConfigurationKey.create<Boolean>("plugin.feature.x")
val OUTPUT_FORMAT = CompilerConfigurationKey.create<String>("plugin.output.format")
val DEBUG_MODE = CompilerConfigurationKey.create<Boolean>("plugin.debug")
}
// Configure plugin settings
configuration.apply {
put(MyPluginConfigurationKeys.ENABLE_FEATURE_X, true)
put(MyPluginConfigurationKeys.OUTPUT_FORMAT, "json")
put(MyPluginConfigurationKeys.DEBUG_MODE, false)
}
// Access in plugin
class MyPlugin {
fun process(configuration: CompilerConfiguration) {
val featureEnabled = configuration.get(MyPluginConfigurationKeys.ENABLE_FEATURE_X) ?: false
val outputFormat = configuration.getNotNull(MyPluginConfigurationKeys.OUTPUT_FORMAT)
if (featureEnabled) {
processWithFeature(outputFormat)
}
}
}fun validateConfiguration(configuration: CompilerConfiguration): List<String> {
val errors = mutableListOf<String>()
// Check required settings
if (!configuration.isSet(CommonConfigurationKeys.MODULE_NAME)) {
errors.add("Module name is required")
}
// Validate JVM settings
val outputDir = configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)
if (outputDir != null && !outputDir.exists()) {
if (!outputDir.mkdirs()) {
errors.add("Cannot create output directory: ${outputDir.path}")
}
}
// Check classpath exists
val classpath = configuration.get(JVMConfigurationKeys.CLASSPATH_ROOTS) ?: emptyList()
classpath.forEach { file ->
if (!file.exists()) {
errors.add("Classpath entry not found: ${file.path}")
}
}
return errors
}
// Usage
val validationErrors = validateConfiguration(configuration)
if (validationErrors.isNotEmpty()) {
validationErrors.forEach { error ->
println("Configuration error: $error")
}
}// Base configuration
val baseConfig = CompilerConfiguration().apply {
put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, languageSettings)
put(CommonConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
}
// JVM-specific configuration inheriting from base
val jvmConfig = baseConfig.copy().apply {
put(JVMConfigurationKeys.JVM_TARGET, JvmTarget.JVM_11)
put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File("build/jvm"))
}
// JS-specific configuration inheriting from base
val jsConfig = baseConfig.copy().apply {
put(JSConfigurationKeys.MODULE_KIND, ModuleKind.COMMON_JS)
put(JSConfigurationKeys.OUTPUT_FILE, "build/js/app.js")
}class ConfigurationException(message: String, cause: Throwable? = null) : Exception(message, cause)
class InvalidConfigurationKeyException(message: String) : ConfigurationException(message)
class MissingConfigurationException(message: String) : ConfigurationException(message)Common configuration errors:
getNotNull())Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-compiler