Оцените файл сценария kotlin с зависимостями
Вопрос: как выполнить набор файлов kotlin во время выполнения и вернуть результат одногоkts
файл от них?
Я пишу систему, которая умеет выполнять kts
файл с инструкциями. На данный момент он поддерживает следующую схему выполнения:
main.kts
- этот файл будет выполнен. Он должен вернутьсяList<Step>
Однако пользователь может поместить любой другой файл в ту же папку. Например, в папке могут быть следующие файлы:
main.kts
Constants.kt
// у него есть константыHelpers.kt
// несколько дополнительных методов
ScriptEngine имеет методы для оценки кода, но имеет только один входной файл.
Вопрос: как я могу попросить ScriptEngine скомпилировать классы в путь к классам, но выполнить только один из них?
Это решение неверно, потому что порядок файлов важен (например, компиляция не выполняется, если первый файл зависит от последнего):
// there is security issue here
val classLoader = Thread.currentThread().contextClassLoader
val engineManager = ScriptEngineManager(classLoader)
setIdeaIoUseFallback()
val ktsEngine: ScriptEngine = engineManager.getEngineByExtension("kts")
/**
* There is issue here: if file1 requires file2 compilation then execution below fails.
*
* Right way: find the solution to compile whole folder and evaluate the single file.
*/
filesFromFolderExceptMain.forEach {
ktsEngine.eval(it)
}
return ktsEngine.eval(mainScriptFile) as List<Step>
Другое решение (которое может привести к непредсказуемым колебаниям компиляции):
val context = filesFromFolderExceptMain.joinToString(System.lineSeparator()
ktsEngine.eval(context)
return ktsEngine.eval(mainScriptFile) as List<Step>
Итак, вопрос: как выполнить набор файлов kotlin во время выполнения и вернуть результат одногоkts
файл от них?
1 ответ
Что вы должны сделать, это добавить @file:Import("Constants.kt", "Helpers.kt")
в основной скрипт (см. https://github.com/Kotlin/KEEP/blob/master/proposals/scripting-support.md). Хотя я не уверен, относится ли это к каталогу, в котором находится скрипт, или к рабочему каталогу.
Если вы не хотите, чтобы пользователи делали это, вы можете передать их в importedScripts
.