Начало работы с пользовательским сценарием Kotlin – учебник
Сценарии Kotlin — это технология, которая позволяет выполнять код Kotlin в виде сценариев без предварительной компиляции или упаковки в исполняемые файлы.
Для обзора сценариев Kotlin с примерами ознакомьтесь с докладом Реализация Gradle Kotlin DSL Родриго Оливейры с KotlinConf'19.
В этом руководстве вы создадите проект сценариев Kotlin, который выполняет произвольный код Kotlin с зависимостями Maven. Вы сможете выполнять сценарии такого типа:
@file:Repository("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven")
@file:DependsOn("org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.3")
import kotlinx.html.*
import kotlinx.html.stream.*
import kotlinx.html.attributes.*
val addressee = "World"
print(
createHTML().html {
body {
h1 { +"Hello, $addressee!" }
}
}
)
Указанная зависимость Maven (kotlinx-html-jvm в этом примере) будет разрешена из указанного репозитория Maven или локального кеша во время выполнения и использована для остальной части сценария.
Структура проекта
Минимальный проект пользовательских сценариев Kotlin содержит две части:
Определение сценария — набор параметров и конфигураций, определяющих, как этот тип сценария должен распознаваться, обрабатываться, компилироваться и выполняться.
Хост сценариев — приложение или компонент, который обрабатывает компиляцию и выполнение сценариев — фактически выполняет сценарии этого типа.
Учитывая все это, лучше разделить проект на два модуля.
Перед началом
Загрузите и установите последнюю версию IntelliJ IDEA.
Создание проекта
В IntelliJ IDEA выберите Файл | Новый | Проект.
В панели слева выберите Создать проект.
-
Назовите новый проект и, при необходимости, измените его расположение.
Из списка Язык выберите Kotlin.
Выберите систему сборки Gradle.
-
Из списка JDK выберите JDK, который вы хотите использовать в проекте.
Если JDK установлен на вашем компьютере, но не определен в IDE, выберите Добавить JDK и укажите путь к домашнему каталогу JDK.
Если у вас нет необходимого JDK на компьютере, выберите Загрузить JDK.
Выберите Kotlin или Gradle для Gradle DSL.
Нажмите Создать.

Добавление модулей сценариев
Теперь у вас есть пустой проект Kotlin/JVM Gradle. Добавьте необходимые модули, определение сценария и хост сценариев:
В IntelliJ IDEA выберите Файл | Новый | Модуль.
В панели слева выберите Новый модуль. Этот модуль будет определением сценария.
Назовите новый модуль и, при необходимости, измените его расположение.
Из списка Язык выберите Java.
Выберите систему сборки Gradle и Kotlin для Gradle DSL, если вы хотите написать скрипт сборки на Kotlin.
В качестве родительского модуля выберите корневой модуль.
-
Нажмите Создать.

В файле
build.gradle(.kts)модуля удалитеversionплагина Kotlin Gradle. Он уже находится в скрипте сборки корневого проекта.Повторите предыдущие шаги еще раз, чтобы создать модуль для хоста сценариев.
Структура проекта должна выглядеть следующим образом:
Вы можете найти пример такого проекта и другие примеры сценариев Kotlin в репозитории GitHub kotlin-script-examples.
Создание определения сценария
Сначала определите тип сценария: что разработчики могут писать в сценариях этого типа и как он будет обрабатываться. В этом руководстве это включает поддержку аннотаций @Repository и @DependsOn в сценариях.
-
В модуле определения сценария добавьте зависимости от компонентов сценариев Kotlin в блок
dependenciesфайлаbuild.gradle(.kts). Эти зависимости предоставят API, которые вам потребуются для определения сценария:dependencies { implementation("org.jetbrains.kotlin:kotlin-scripting-common") implementation("org.jetbrains.kotlin:kotlin-scripting-jvm") implementation("org.jetbrains.kotlin:kotlin-scripting-dependencies") implementation("org.jetbrains.kotlin:kotlin-scripting-dependencies-maven") // coroutines dependency is required for this particular definition implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4") }dependencies { implementation 'org.jetbrains.kotlin:kotlin-scripting-common' implementation 'org.jetbrains.kotlin:kotlin-scripting-jvm' implementation 'org.jetbrains.kotlin:kotlin-scripting-dependencies' implementation 'org.jetbrains.kotlin:kotlin-scripting-dependencies-maven' // coroutines dependency is required for this particular definition implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4' } Создайте директорию
src/main/kotlin/в модуле и добавьте Kotlin-файл, например,scriptDef.kt.-
В
scriptDef.kt, создайте класс. Он будет суперклассом для сценариев этого типа, поэтому объявите егоabstractилиopen.// abstract (or open) superclass for scripts of this type abstract class ScriptWithMavenDeps
Этот класс также будет служить ссылкой на определение сценария позже.
-
Чтобы сделать класс определением сценария, отметьте его аннотацией
@KotlinScript. Передайте два параметра в аннотацию:fileExtension— строка, заканчивающаяся на.kts, которая определяет расширение файла для сценариев этого типа.compilationConfiguration— класс Kotlin, который расширяетScriptCompilationConfigurationи определяет особенности компиляции для этого определения сценария. Вы создадите его на следующем шаге.
// @KotlinScript annotation marks a script definition class @KotlinScript( // File extension for the script type fileExtension = "scriptwithdeps.kts", // Compilation configuration for the script type compilationConfiguration = ScriptWithMavenDepsConfiguration::class ) abstract class ScriptWithMavenDeps object ScriptWithMavenDepsConfiguration: ScriptCompilationConfiguration() -
Определите конфигурацию компиляции сценария, как показано ниже.
object ScriptWithMavenDepsConfiguration : ScriptCompilationConfiguration( { // Implicit imports for all scripts of this type defaultImports(DependsOn::class, Repository::class) jvm { // Extract the whole classpath from context classloader and use it as dependencies dependenciesFromCurrentContext(wholeClasspath = true) } // Callbacks refineConfiguration { // Process specified annotations with the provided handler onAnnotations(DependsOn::class, Repository::class, handler = ::configureMavenDepsOnAnnotations) } } )Функция
configureMavenDepsOnAnnotationsвыглядит следующим образом:// Handler that reconfigures the compilation on the fly fun configureMavenDepsOnAnnotations(context: ScriptConfigurationRefinementContext): ResultWithDiagnostics<ScriptCompilationConfiguration> { val annotations = context.collectedData?.get(ScriptCollectedData.collectedAnnotations)?.takeIf { it.isNotEmpty() } ?: return context.compilationConfiguration.asSuccess() return runBlocking { resolver.resolveFromScriptSourceAnnotations(annotations) }.onSuccess { context.compilationConfiguration.with { dependencies.append(JvmDependency(it)) }.asSuccess() } } private val resolver = CompoundDependenciesResolver(FileSystemDependenciesResolver(), MavenDependenciesResolver())Полный код можно найти здесь.
Создание хоста скриптов
Следующим шагом является создание хоста скриптов — компонента, отвечающего за выполнение скриптов.
-
В модуле хоста скриптов добавьте зависимости в блок
dependenciesвbuild.gradle(.kts):Компоненты Kotlin scripting, предоставляющие необходимые API для хоста скриптов
Модуль определения скрипта, созданный ранее
dependencies { implementation("org.jetbrains.kotlin:kotlin-scripting-common") implementation("org.jetbrains.kotlin:kotlin-scripting-jvm") implementation("org.jetbrains.kotlin:kotlin-scripting-jvm-host") implementation(project(":script-definition")) // the script definition module }dependencies { implementation 'org.jetbrains.kotlin:kotlin-scripting-common' implementation 'org.jetbrains.kotlin:kotlin-scripting-jvm' implementation 'org.jetbrains.kotlin:kotlin-scripting-jvm-host' implementation project(':script-definition') // the script definition module } Создайте директорию
src/main/kotlin/в модуле и добавьте файл Kotlin-исходника, например,host.kt.-
Определите функцию
mainдля приложения. В её теле проверьте, что она имеет один аргумент — путь к файлу скрипта — и выполните скрипт. Вы определите выполнение скрипта в отдельной функцииevalFileна следующем шаге. Объявите её пустой пока.mainможет выглядеть так:fun main(vararg args: String) { if (args.size != 1) { println("usage: <app> <script file>") } else { val scriptFile = File(args[0]) println("Executing script $scriptFile") evalFile(scriptFile) } } -
Определите функцию оценки скрипта. Именно здесь вы будете использовать определение скрипта. Получите его, вызвав
createJvmCompilationConfigurationFromTemplateс классом определения скрипта в качестве параметра типа. Затем вызовитеBasicJvmScriptingHost().eval, передав в него код скрипта и его конфигурацию компиляции.evalвозвращает экземплярResultWithDiagnostics, поэтому установите его в качестве возвращаемого типа вашей функции.fun evalFile(scriptFile: File): ResultWithDiagnostics<EvaluationResult> { val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<ScriptWithMavenDeps>() return BasicJvmScriptingHost().eval(scriptFile.toScriptSource(), compilationConfiguration, null) } -
Отрегулируйте функцию
mainдля вывода информации о выполнении скрипта:fun main(vararg args: String) { if (args.size != 1) { println("usage: <app> <script file>") } else { val scriptFile = File(args[0]) println("Executing script $scriptFile") val res = evalFile(scriptFile) res.reports.forEach { if (it.severity > ScriptDiagnostic.Severity.DEBUG) { println(" : ${it.message}" + if (it.exception == null) "" else ": ${it.exception}") } } } }
Полный код вы можете найти здесь
Запуск скриптов
Чтобы проверить работу вашего хоста скриптов, подготовьте скрипт для выполнения и конфигурацию запуска.
-
Создайте файл
html.scriptwithdeps.ktsс указанным содержимым в корне проекта:@file:Repository("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven") @file:DependsOn("org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.3") import kotlinx.html.*; import kotlinx.html.stream.*; import kotlinx.html.attributes.* val addressee = "World" print( createHTML().html { body { h1 { +"Hello, $addressee!" } } } )Он использует функции из библиотеки
kotlinx-html-jvm, на которую есть ссылка в аргументе аннотации@DependsOn. -
Создайте конфигурацию запуска, которая запускает хост скриптов и выполняет этот файл:
Откройте
host.ktи перейдите к функцииmain. На ней слева есть значок Запуск.Щёлкните правой кнопкой мыши значок и выберите Изменить конфигурацию запуска.
-
В диалоговом окне Создание конфигурации запуска добавьте имя файла скрипта в Аргументы программы и нажмите ОК.

Запустите созданную конфигурацию.
Вы увидите, как скрипт выполняется, обрабатывая зависимость от kotlinx-html-jvm в указанном репозитории и выводя результаты вызова его функций:
<html>
<body>
<h1>Hello, World!</h1>
</body>
</html>
Разрешение зависимостей может занять некоторое время при первом запуске. Последующие запуски будут выполняться намного быстрее, так как они используют загруженные зависимости из локального репозитория Maven.
Что дальше?
После создания простого проекта Kotlin scripting, найдите более подробную информацию по этой теме:
Прочитайте Kotlin scripting KEEP
Посмотрите примеры Kotlin scripting
Посмотрите презентацию Реализация Gradle Kotlin DSL Rodrigo Oliveira
© 2010–2022 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/custom-script-deps-tutorial.html