如何在内存中运行编译kotlin文件的测试并检查结果?

到目前为止,我有

import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler MyProjectCompiler.initialize("SampleKtFileOutput") .packageName("com.test.sample") .compile(File(someFile.path)) .result { ktSource: String -> K2JVMCompiler() .exec(System.out, /** arguments here?*/) } 

这个手动启动编译器,但我想从第一个编译器(生成kotlin源的MyProjectCompiler生成的字符串在内存中,并检查结果而不写入文件。

如果可能的话,我想包括当前类路径中的所有内容。

读取K2JVMCompiler类的源代码,似乎编译器只支持编译文件。 深入挖掘,似乎过于复杂,假的org.jetbrains.kotlin.codegen.KotlinCodegenFacade静态方法的条目compileCorrectFiles

你最好猜测它使用文件系统来做到这一点。 临时的RAM磁盘可能适合您的需求。 (例如,这是内置的macOS)

我发现最简单的方法是使用原始问题中的代码,并使用java.io.tmpdir 。 这是一个可重复使用的解决方案:

添加kotlin编译器作为测试依赖项:

 testCompile group: 'org.jetbrains.kotlin', name: 'kotlin-compiler', version: "$kotlin_version" 

编译器的包装器:

 object JvmCompile { fun exe(input: File, output: File): Boolean = K2JVMCompiler().run { val args = K2JVMCompilerArguments().apply { freeArgs = listOf(input.absolutePath) loadBuiltInsFromDependencies = true destination = output.absolutePath classpath = System.getProperty("java.class.path") .split(System.getProperty("path.separator")) .filter { it.asFile().exists() && it.asFile().canRead() }.joinToString(":") noStdlib = true noReflect = true skipRuntimeVersionCheck = true reportPerf = true } output.deleteOnExit() execImpl( PrintingMessageCollector( System.out, MessageRenderer.WITHOUT_PATHS, true), Services.EMPTY, args) }.code == 0 } 

用于从编译的类创建对象的类加载器:

 class Initializer(private val root: File) { val loader = URLClassLoader( listOf(root.toURI().toURL()).toTypedArray(), this::class.java.classLoader) @Suppress("UNCHECKED_CAST") inline fun <reified T> loadCompiledObject(clazzName: String): T? = loader.loadClass(clazzName).kotlin.objectInstance as T @Suppress("UNCHECKED_CAST") inline fun <reified T> createInstance(clazzName: String): T? = loader.loadClass(clazzName).kotlin.createInstance() as T } 

示例测试用例:

首先制作一个kotlin源文件

 MockClasswriter(""" | |package com.test | |class Example : Consumer<String> { | override fun accept(value: String) { | println("found: '$\value'") | } |} """.trimMargin("|")) .writeToFile(codegenOutputFile) 

确保它编译:

 assertTrue(JvmCompile.exe(codegenOutputFile, compileOutputDir)) 

加载类作为接口实例

 Initializer(compileOutputDir) .createInstance<Consumer<String>>("com.test.Example") ?.accept("Hello, world!") 

输出将如预期: found: 'Hello, world!'