The Kotlin compiler infrastructure providing JVM, JavaScript, and metadata compilation capabilities
—
Comprehensive environment management for Kotlin compilation projects including dependency resolution, file system setup, project configuration, and IntelliJ platform integration. The environment system provides isolation and proper resource management for compilation tasks.
Central environment management providing project setup, dependency resolution, and resource lifecycle management.
/**
* Central environment for Kotlin compilation
* Manages project setup, dependencies, and IntelliJ platform integration
*/
class KotlinCoreEnvironment private constructor() {
/** IntelliJ project instance */
val project: Project
/** Compiler configuration */
val configuration: CompilerConfiguration
/** Source files in the project */
val getSourceFiles: List<KtFile>
companion object {
/**
* Create environment for production compilation
*
* @param parentDisposable Parent disposable for resource cleanup
* @param configuration Compiler configuration
* @param configFiles Environment configuration files
* @return Configured compilation environment
*/
fun createForProduction(
parentDisposable: Disposable,
configuration: CompilerConfiguration,
configFiles: EnvironmentConfigFiles
): KotlinCoreEnvironment
/**
* Create environment for tests
*
* @param parentDisposable Parent disposable for resource cleanup
* @param configuration Compiler configuration
* @param extensionRegistrars Additional extension registrars
* @param configFiles Environment configuration files
* @return Test compilation environment
*/
fun createForTests(
parentDisposable: Disposable,
configuration: CompilerConfiguration,
extensionRegistrars: List<EnvironmentExtension>,
configFiles: EnvironmentConfigFiles
): KotlinCoreEnvironment
/**
* Get or create application environment
*
* @param parentDisposable Parent disposable
* @param configuration Compiler configuration
* @return Application environment instance
*/
fun getOrCreateApplicationEnvironmentForProduction(
parentDisposable: Disposable,
configuration: CompilerConfiguration
): ApplicationEnvironment
}
/**
* Create package part provider for dependencies
*
* @param scope Global search scope
* @return Package part provider instance
*/
fun createPackagePartProvider(scope: GlobalSearchScope): PackagePartProvider
/**
* Project environment for managing project-level resources
*/
class ProjectEnvironment(
val parentDisposable: Disposable,
val applicationEnvironment: ApplicationEnvironment,
val configuration: CompilerConfiguration
) {
val project: MockProject
/**
* Register project extensions
*
* @param extensions Extensions to register
*/
fun registerExtensions(extensions: List<EnvironmentExtension>)
}
}Platform and target-specific environment configuration file sets.
/**
* Configuration files for different compilation targets
* Defines which IntelliJ platform components to load
*/
enum class EnvironmentConfigFiles(
private val configFiles: List<String>
) {
/** JVM compilation configuration */
JVM_CONFIG_FILES(listOf(
"intellij.platform.resources.xml",
"intellij.java.xml",
"intellij.kotlin.xml"
)),
/** JavaScript compilation configuration */
JS_CONFIG_FILES(listOf(
"intellij.platform.resources.xml",
"intellij.javascript.xml",
"intellij.kotlin.xml"
)),
/** Metadata-only compilation configuration */
METADATA_CONFIG_FILES(listOf(
"intellij.platform.resources.xml",
"intellij.kotlin.xml"
)),
/** Native compilation configuration */
NATIVE_CONFIG_FILES(listOf(
"intellij.platform.resources.xml",
"intellij.kotlin.xml",
"intellij.kotlin.native.xml"
));
/**
* Get configuration file paths
*
* @return List of configuration file paths
*/
fun getConfigFiles(): List<String> = configFiles
}Kotlin installation and library path management.
/**
* Kotlin installation paths and library locations
* Provides access to standard library and compiler jars
*/
interface KotlinPaths {
/** Kotlin installation home directory */
val homePath: File
/** Kotlin standard library JAR */
val stdlibPath: File
/** Kotlin script runtime JAR */
val scriptRuntimePath: File
/** Kotlin reflect library JAR */
val reflectPath: File
/** Kotlin test library JAR */
val kotlinTestPath: File
/** Kotlin stdlib sources JAR */
val stdlibSourcesPath: File
/** All runtime JARs */
val runtimeJars: List<File>
/** Compiler JAR */
val compilerPath: File
/** JS standard library */
val jsStdLibJarPath: File
/** JS Kotlin test library */
val jsKotlinTestJarPath: File
/** All JS library JARs */
val jsLibJars: List<File>
}
/**
* Path utilities for Kotlin installation detection
*/
object PathUtil {
/**
* Get Kotlin paths from compiler JAR
*
* @param compilerJar Compiler JAR file
* @return Kotlin paths instance
*/
fun getKotlinPathsForCompiler(compilerJar: File): KotlinPaths
/**
* Get Kotlin paths from distribution
*
* @param kotlinHome Kotlin home directory
* @return Kotlin paths instance
*/
fun getKotlinPathsForDistribution(kotlinHome: File): KotlinPaths
/**
* Get Kotlin paths for IDE plugin
*
* @param ideaPluginPath IDE plugin path
* @return Kotlin paths instance
*/
fun getKotlinPathsForIdeaPlugin(ideaPluginPath: File): KotlinPaths
/**
* Get JDK classpath roots
*
* @param jdkHome JDK home directory
* @return List of JDK JAR files
*/
fun getJdkClasspathRoots(jdkHome: File): List<File>
}Source file and library content root management.
/**
* Base class for content roots (source directories, libraries)
*/
abstract class ContentRoot {
/** Content root file */
abstract val file: File
}
/**
* Source directory content root
*/
class KotlinSourceRoot(
override val file: File,
val isCommon: Boolean = false,
val packagePrefix: String? = null
) : ContentRoot()
/**
* Java source directory content root
*/
class JavaSourceRoot(
override val file: File,
val packagePrefix: String? = null
) : ContentRoot()
/**
* JAR or directory library content root
*/
class JvmClasspathRoot(
override val file: File
) : ContentRoot()
/**
* JavaScript library content root
*/
class JsLibrarySourceRoot(
override val file: File
) : ContentRoot()Compilation module and dependency management.
/**
* Compilation module definition
*/
class Module(
val moduleName: String,
val outputDirectory: File,
val sources: List<File>,
val classpath: List<File>,
val friends: List<File> = emptyList()
) {
/**
* Get module identifier
*
* @return Module identifier string
*/
fun getModuleId(): String = moduleName
}
/**
* Module builder for configuring compilation modules
*/
class ModuleBuilder(private val moduleName: String) {
private val sources = mutableListOf<File>()
private val classpath = mutableListOf<File>()
private var outputDirectory: File? = null
/**
* Add source file or directory
*
* @param source Source file or directory
* @return Builder for chaining
*/
fun addSourceFiles(vararg source: File): ModuleBuilder {
sources.addAll(source)
return this
}
/**
* Add classpath entry
*
* @param cp Classpath file (JAR or directory)
* @return Builder for chaining
*/
fun addClasspathEntry(cp: File): ModuleBuilder {
classpath.add(cp)
return this
}
/**
* Set output directory
*
* @param output Output directory
* @return Builder for chaining
*/
fun setOutputDirectory(output: File): ModuleBuilder {
outputDirectory = output
return this
}
/**
* Build module instance
*
* @return Configured module
*/
fun build(): Module {
return Module(
moduleName = moduleName,
outputDirectory = outputDirectory ?: File("build"),
sources = sources.toList(),
classpath = classpath.toList()
)
}
}
/**
* Module chunk for batch compilation
*/
class ModuleChunk(val modules: List<Module>) {
/**
* Get all source files in chunk
*
* @return All source files across modules
*/
fun getSourceFiles(): List<File> {
return modules.flatMap { it.sources }
}
/**
* Get combined classpath
*
* @return Combined classpath from all modules
*/
fun getClasspath(): List<File> {
return modules.flatMap { it.classpath }.distinct()
}
}Extension mechanism for customizing environment setup.
/**
* Environment extension for customizing compilation environment
*/
interface EnvironmentExtension {
/**
* Register extension components
*
* @param project Project instance
* @param configuration Compiler configuration
*/
fun registerProjectExtensions(
project: MockProject,
configuration: CompilerConfiguration
)
}
/**
* Extension registrar for grouping related extensions
*/
interface EnvironmentExtensionRegistrar {
/**
* Get extensions to register
*
* @return List of environment extensions
*/
fun getExtensions(): List<EnvironmentExtension>
}Source file discovery and virtual file system management.
/**
* Kotlin source file representation
*/
abstract class KtFile : KtElement {
/** Virtual file backing this source file */
val virtualFile: VirtualFile
/** Package directive */
val packageDirective: KtPackageDirective?
/** Import directives */
val importDirectives: List<KtImportDirective>
/** Top-level declarations */
val declarations: List<KtDeclaration>
/** File annotation list */
val fileAnnotationList: KtFileAnnotationList?
/**
* Check if file is script
*
* @return true if file is Kotlin script (.kts)
*/
fun isScript(): Boolean
}
/**
* Virtual file system utilities
*/
object VfsUtil {
/**
* Find files by extension
*
* @param root Root directory
* @param extension File extension (without dot)
* @return List of matching virtual files
*/
fun findFilesByExtension(root: VirtualFile, extension: String): List<VirtualFile>
/**
* Create virtual file from physical file
*
* @param file Physical file
* @return Virtual file representation
*/
fun findFileByIoFile(file: File): VirtualFile?
}import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import com.intellij.openapi.util.Disposer
import java.io.File
// Create disposable for resource management
val parentDisposable = Disposer.newDisposable()
try {
// Configure compilation
val configuration = CompilerConfiguration().apply {
put(CommonConfigurationKeys.MODULE_NAME, "my-project")
put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File("build/classes"))
put(JVMConfigurationKeys.CLASSPATH_ROOTS, listOf(
File("lib/kotlin-stdlib.jar")
))
// Add source roots
put(CommonConfigurationKeys.CONTENT_ROOTS, listOf(
KotlinSourceRoot(File("src/main/kotlin")),
JavaSourceRoot(File("src/main/java"))
))
}
// Create environment
val environment = KotlinCoreEnvironment.createForProduction(
parentDisposable = parentDisposable,
configuration = configuration,
configFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES
)
// Access source files
val sourceFiles = environment.getSourceFiles()
println("Found ${sourceFiles.size} source files")
sourceFiles.forEach { ktFile ->
println("Processing: ${ktFile.virtualFile.path}")
// Access file content
ktFile.declarations.forEach { declaration ->
println(" Declaration: ${declaration.name}")
}
}
} finally {
// Clean up resources
Disposer.dispose(parentDisposable)
}import org.jetbrains.kotlin.cli.jvm.compiler.ModuleChunk
import org.jetbrains.kotlin.cli.jvm.compiler.ModuleBuilder
// Build modules
val coreModule = ModuleBuilder("core")
.addSourceFiles(File("src/core/kotlin"))
.addClasspathEntry(File("lib/kotlin-stdlib.jar"))
.setOutputDirectory(File("build/core"))
.build()
val apiModule = ModuleBuilder("api")
.addSourceFiles(File("src/api/kotlin"))
.addClasspathEntry(File("lib/kotlin-stdlib.jar"))
.addClasspathEntry(File("build/core")) // Depend on core
.setOutputDirectory(File("build/api"))
.build()
// Create module chunk
val moduleChunk = ModuleChunk(listOf(coreModule, apiModule))
// Configure for multi-module compilation
val configuration = CompilerConfiguration().apply {
put(CommonConfigurationKeys.MODULES, moduleChunk.modules)
// Set combined classpath
put(JVMConfigurationKeys.CLASSPATH_ROOTS, moduleChunk.getClasspath())
}
val environment = KotlinCoreEnvironment.createForProduction(
parentDisposable = parentDisposable,
configuration = configuration,
configFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES
)import org.jetbrains.kotlin.utils.PathUtil
import org.jetbrains.kotlin.utils.KotlinPaths
// Detect Kotlin installation
val kotlinHome = File("/usr/local/kotlin")
val kotlinPaths = PathUtil.getKotlinPathsForDistribution(kotlinHome)
// Configure with detected paths
val configuration = CompilerConfiguration().apply {
put(JVMConfigurationKeys.CLASSPATH_ROOTS, listOf(
kotlinPaths.stdlibPath,
kotlinPaths.reflectPath,
kotlinPaths.kotlinTestPath
))
}
// Alternative: Detect from compiler JAR
val compilerJar = File("lib/kotlin-compiler.jar")
val pathsFromCompiler = PathUtil.getKotlinPathsForCompiler(compilerJar)
println("Kotlin home: ${pathsFromCompiler.homePath}")
println("Stdlib: ${pathsFromCompiler.stdlibPath}")
println("Runtime JARs: ${pathsFromCompiler.runtimeJars}")import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
// JavaScript-specific configuration
val jsConfiguration = CompilerConfiguration().apply {
put(CommonConfigurationKeys.MODULE_NAME, "js-app")
put(JSConfigurationKeys.OUTPUT_FILE, "build/js/app.js")
put(JSConfigurationKeys.MODULE_KIND, ModuleKind.COMMON_JS)
put(JSConfigurationKeys.LIBRARIES, listOf("lib/kotlin-stdlib-js.jar"))
// Add JS sources
put(CommonConfigurationKeys.CONTENT_ROOTS, listOf(
KotlinSourceRoot(File("src/main/kotlin"))
))
}
// Create JS environment
val jsEnvironment = KotlinCoreEnvironment.createForProduction(
parentDisposable = parentDisposable,
configuration = jsConfiguration,
configFiles = EnvironmentConfigFiles.JS_CONFIG_FILES
)// Custom environment extension
class MyEnvironmentExtension : EnvironmentExtension {
override fun registerProjectExtensions(
project: MockProject,
configuration: CompilerConfiguration
) {
// Register custom extensions
SyntheticResolveExtension.registerExtension(
project,
MySyntheticResolveExtension()
)
IrGenerationExtension.registerExtension(
project,
MyIrGenerationExtension()
)
}
}
// Environment with custom extensions
val extensions = listOf(MyEnvironmentExtension())
val environment = KotlinCoreEnvironment.createForTests(
parentDisposable = parentDisposable,
configuration = configuration,
extensionRegistrars = extensions,
configFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES
)// Create project environment separately
val applicationEnvironment = KotlinCoreEnvironment.getOrCreateApplicationEnvironmentForProduction(
parentDisposable = parentDisposable,
configuration = configuration
)
val projectEnvironment = KotlinCoreEnvironment.ProjectEnvironment(
parentDisposable = parentDisposable,
applicationEnvironment = applicationEnvironment,
configuration = configuration
)
// Register project-specific extensions
projectEnvironment.registerExtensions(listOf(
MyEnvironmentExtension(),
AnotherCustomExtension()
))
// Access project
val project = projectEnvironment.project
val packagePartProvider = KotlinCoreEnvironment.createPackagePartProvider(
GlobalSearchScope.allScope(project)
)// Proper resource management with try-with-resources pattern
class CompilationSession : AutoCloseable {
private val parentDisposable = Disposer.newDisposable()
private val environment: KotlinCoreEnvironment
init {
val configuration = CompilerConfiguration().apply {
// Configure compilation settings
}
environment = KotlinCoreEnvironment.createForProduction(
parentDisposable = parentDisposable,
configuration = configuration,
configFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES
)
}
fun compile(): Boolean {
return try {
val sourceFiles = environment.getSourceFiles()
// Perform compilation
true
} catch (e: Exception) {
false
}
}
override fun close() {
Disposer.dispose(parentDisposable)
}
}
// Usage with automatic cleanup
CompilationSession().use { session ->
val success = session.compile()
println("Compilation ${if (success) "succeeded" else "failed"}")
}// Debug environment configuration
fun debugEnvironment(environment: KotlinCoreEnvironment) {
val configuration = environment.configuration
val project = environment.project
println("=== Environment Debug Info ===")
println("Module name: ${configuration.get(CommonConfigurationKeys.MODULE_NAME)}")
println("Source files: ${environment.getSourceFiles().size}")
// Debug content roots
val contentRoots = configuration.get(CommonConfigurationKeys.CONTENT_ROOTS) ?: emptyList()
println("Content roots:")
contentRoots.forEach { root ->
println(" ${root.javaClass.simpleName}: ${root.file}")
}
// Debug classpath
val classpath = configuration.get(JVMConfigurationKeys.CLASSPATH_ROOTS) ?: emptyList()
println("Classpath:")
classpath.forEach { jar ->
println(" ${jar.path} (exists: ${jar.exists()})")
}
// Debug project extensions
println("Registered extensions:")
project.extensionArea.getExtensionPoint<Any>("*").extensions.forEach { ext ->
println(" ${ext.javaClass.name}")
}
}class EnvironmentException(message: String, cause: Throwable? = null) : Exception(message, cause)
class InvalidEnvironmentConfigurationException(message: String) : EnvironmentException(message)
class MissingKotlinHomeException(message: String) : EnvironmentException(message)Common environment errors:
Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-compiler