@@ -2,6 +2,7 @@ package com.compiler.server.compiler.components
22
33import com.compiler.server.executor.CommandLineArgument
44import com.compiler.server.executor.JavaExecutor
5+ import com.compiler.server.model.CompilerDiagnostics
56import com.compiler.server.model.ExtendedCompilerArgument
67import com.compiler.server.model.JvmExecutionResult
78import com.compiler.server.model.OutputDirectory
@@ -12,7 +13,9 @@ import com.compiler.server.utils.CompilerArgumentsUtil
1213import component.KotlinEnvironment
1314import executors.JUnitExecutors
1415import executors.JavaRunnerExecutor
15- import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
16+ import org.jetbrains.kotlin.buildtools.api.ExperimentalBuildToolsApi
17+ import org.jetbrains.kotlin.buildtools.api.KotlinToolchains
18+ import org.jetbrains.kotlin.buildtools.api.jvm.JvmPlatformToolchain
1619import org.jetbrains.org.objectweb.asm.ClassReader
1720import org.jetbrains.org.objectweb.asm.ClassReader.*
1821import org.jetbrains.org.objectweb.asm.ClassVisitor
@@ -63,7 +66,12 @@ class KotlinCompiler(
6366 ?.joinToString(" \n\n " )
6467 }
6568
66- fun run (files : List <ProjectFile >, addByteCode : Boolean , args : String , userCompilerArguments : Map <String , Any >): JvmExecutionResult {
69+ fun run (
70+ files : List <ProjectFile >,
71+ addByteCode : Boolean ,
72+ args : String ,
73+ userCompilerArguments : Map <String , Any >
74+ ): JvmExecutionResult {
6775 return execute(files, addByteCode, userCompilerArguments) { output, compiled ->
6876 val mainClass = JavaRunnerExecutor ::class .java.name
6977 val compiledMainClass = when (compiled.mainClasses.size) {
@@ -86,37 +94,86 @@ class KotlinCompiler(
8694 }
8795 }
8896
89- fun test (files : List <ProjectFile >, addByteCode : Boolean , userCompilerArguments : Map <String , Any >): JvmExecutionResult {
97+ fun test (
98+ files : List <ProjectFile >,
99+ addByteCode : Boolean ,
100+ userCompilerArguments : Map <String , Any >
101+ ): JvmExecutionResult {
90102 return execute(files, addByteCode, userCompilerArguments) { output, _ ->
91103 val mainClass = JUnitExecutors ::class .java.name
92104 javaExecutor.execute(argsFrom(mainClass, output, listOf (output.path.toString())))
93105 .asJUnitExecutionResult()
94106 }
95107 }
96108
97- @OptIn(ExperimentalPathApi ::class )
98- fun compile (files : List <ProjectFile >, userCompilerArguments : Map <String , Any >): CompilationResult <JvmClasses > = usingTempDirectory { inputDir ->
99- val ioFiles = files.writeToIoFiles(inputDir)
100- usingTempDirectory { outputDir ->
101- val arguments = ioFiles.map { it.absolutePathString() } +
102- compilerArgumentsUtil.convertCompilerArgumentsToCompilationString(jvmCompilerArguments, compilerArgumentsUtil.PREDEFINED_JVM_ARGUMENTS , userCompilerArguments) +
103- listOf (" -d" , outputDir.absolutePathString())
104- K2JVMCompiler ().tryCompilation(inputDir, ioFiles, arguments) {
105- val outputFiles = buildMap {
106- outputDir.visitFileTree {
107- onVisitFile { file, _ ->
108- put(file.relativeTo(outputDir).pathString, file.readBytes())
109- FileVisitResult .CONTINUE
110- }
109+ fun compile (files : List <ProjectFile >, userCompilerArguments : Map <String , Any >): CompilationResult <JvmClasses > =
110+ usingTempDirectory { inputDir ->
111+ val ioFiles = files.writeToIoFiles(inputDir)
112+ usingTempDirectory { outputDir ->
113+ val arguments = ioFiles.map { it.absolutePathString() } +
114+ compilerArgumentsUtil.convertCompilerArgumentsToCompilationString(
115+ jvmCompilerArguments,
116+ compilerArgumentsUtil.PREDEFINED_JVM_ARGUMENTS ,
117+ userCompilerArguments
118+ )
119+ val result = compileWithToolchain(inputDir, outputDir, arguments)
120+ return @usingTempDirectory result
121+ }
122+ }
123+
124+ @OptIn(ExperimentalPathApi ::class , ExperimentalBuildToolsApi ::class , ExperimentalBuildToolsApi ::class )
125+ private fun compileWithToolchain (
126+ inputDir : Path ,
127+ outputDir : Path ,
128+ arguments : List <String >
129+ ): CompilationResult <JvmClasses > {
130+ val sources = inputDir.listDirectoryEntries()
131+
132+ val logger = CompilationLogger ()
133+ logger.compilationLogs = sources
134+ .filter { it.name.endsWith(" .kt" ) }
135+ .associate { it.name to mutableListOf () }
136+
137+ val toolchains = KotlinToolchains .loadImplementation(ClassLoader .getSystemClassLoader())
138+ val jvmToolchain = toolchains.getToolchain(JvmPlatformToolchain ::class .java)
139+ val operation = jvmToolchain.createJvmCompilationOperation(sources, outputDir)
140+ operation.compilerArguments.applyArgumentStrings(arguments)
141+
142+ toolchains.createBuildSession().use { session ->
143+ val result = try {
144+ session.executeOperation(operation, toolchains.createInProcessExecutionPolicy(), logger)
145+ } catch (e: Exception ) {
146+ throw Exception (" Exception executing compilation operation" , e)
147+ }
148+ return toCompilationResult(result, logger, outputDir)
149+ }
150+ }
151+
152+ private fun toCompilationResult (
153+ buildResult : org.jetbrains.kotlin.buildtools.api.CompilationResult ,
154+ logger : CompilationLogger ,
155+ outputDir : Path ,
156+ ): CompilationResult <JvmClasses > = when (buildResult) {
157+ org.jetbrains.kotlin.buildtools.api.CompilationResult .COMPILATION_SUCCESS -> {
158+ val compilerDiagnostics = CompilerDiagnostics (logger.compilationLogs)
159+ val outputFiles = buildMap {
160+ outputDir.visitFileTree {
161+ onVisitFile { file, _ ->
162+ put(file.relativeTo(outputDir).pathString, file.readBytes())
163+ FileVisitResult .CONTINUE
111164 }
112165 }
113- val mainClasses = findMainClasses(outputFiles)
114- JvmClasses (
166+ }
167+ Compiled (
168+ compilerDiagnostics = compilerDiagnostics,
169+ result = JvmClasses (
115170 files = outputFiles,
116- mainClasses = mainClasses ,
171+ mainClasses = findMainClasses(outputFiles) ,
117172 )
118- }
173+ )
119174 }
175+
176+ else -> NotCompiled (CompilerDiagnostics (logger.compilationLogs))
120177 }
121178
122179 private fun findMainClasses (outputFiles : Map <String , ByteArray >): Set <String > =
0 commit comments