Skip to content

Kotlinカスタムスクリプトの始め方 – チュートリアル

Kotlinカスタムスクリプトは実験的です。これは予告なく廃止または変更される可能性があります。 評価目的のみにご使用ください。YouTrackでフィードバックをお待ちしております。

_Kotlinスクリプト_は、Kotlinコードを事前コンパイルや実行可能ファイルへのパッケージングなしにスクリプトとして実行可能にする技術です。

Kotlinスクリプトの概要と例については、KotlinConf'19でのRodrigo Oliveira氏によるトークImplementing the Gradle Kotlin DSLをご覧ください。

このチュートリアルでは、Maven依存関係を持つ任意のKotlinコードを実行するKotlinスクリプトプロジェクトを作成します。 次のようなスクリプトを実行できるようになります。

kotlin
@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カスタムスクリプトプロジェクトは、2つの部分で構成されます。

  • スクリプト定義 – このスクリプトタイプがどのように認識され、処理され、コンパイルされ、実行されるかを定義する、パラメーターと構成のセット。
  • スクリプトホスト – スクリプトのコンパイルと実行を処理するアプリケーションまたはコンポーネント。実際にこのタイプのスクリプトを実行します。

これらすべてを考慮すると、プロジェクトを2つのモジュールに分割するのが最善です。

始める前に

IntelliJ IDEAの最新バージョンをダウンロードしてインストールしてください。

プロジェクトを作成する

  1. IntelliJ IDEAで、File | New | Projectを選択します。

  2. 左側のパネルで、New Projectを選択します。

  3. 新しいプロジェクトに名前を付け、必要に応じてその場所を変更します。

    Create Git repositoryチェックボックスを選択して、新しいプロジェクトをバージョン管理下に置きます。後からいつでも行うことができます。

  4. Languageリストから、Kotlinを選択します。

  5. Gradleビルドシステムを選択します。

  6. JDKリストから、プロジェクトで使用したいJDKを選択します。

    • JDKがコンピューターにインストールされているが、IDEで定義されていない場合、Add JDKを選択し、JDKホームディレクトリへのパスを指定します。
    • 必要なJDKがコンピューターにない場合、Download JDKを選択します。
  7. Gradle DSLの言語としてKotlinまたはGradleを選択します。

  8. Createをクリックします。

カスタムKotlinスクリプトのルートプロジェクトを作成

スクリプトモジュールを追加する

これで、空のKotlin/JVM Gradleプロジェクトができました。必要なモジュールであるスクリプト定義とスクリプトホストを追加します。

  1. IntelliJ IDEAで、File | New | Moduleを選択します。
  2. 左側のパネルで、New Moduleを選択します。このモジュールがスクリプト定義になります。
  3. 新しいモジュールに名前を付け、必要に応じてその場所を変更します。
  4. Languageリストから、Javaを選択します。
  5. ビルドスクリプトをKotlinで記述したい場合、GradleビルドシステムとGradle DSLにKotlinを選択します。
  6. モジュールの親として、ルートモジュールを選択します。
  7. Createをクリックします。

スクリプト定義モジュールを作成

  1. モジュールのbuild.gradle(.kts)ファイルで、Kotlin Gradleプラグインのversionを削除します。これはすでにルートプロジェクトのビルドスクリプトに含まれています。

  2. 前のステップをもう一度繰り返して、スクリプトホスト用のモジュールを作成します。

プロジェクトは次の構造になっているはずです。

カスタムスクリプトプロジェクトの構造

このようなプロジェクトの例やその他のKotlinスクリプトの例は、kotlin-script-examples GitHubリポジトリで見つけることができます。

スクリプト定義を作成する

まず、スクリプトタイプを定義します。開発者がこのタイプのスクリプトで何を書けるか、そしてそれがどのように処理されるかです。 このチュートリアルでは、スクリプト内の@Repositoryおよび@DependsOnアノテーションのサポートが含まれます。

  1. スクリプト定義モジュールで、build.gradle(.kts)dependenciesブロックにKotlinスクリプトコンポーネントへの依存関係を追加します。これらの依存関係は、スクリプト定義に必要なAPIを提供します。

    kotlin
    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.10.2") 
    }
    groovy
    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.10.2'
    
    }
  2. モジュール内にsrc/main/kotlin/ディレクトリを作成し、例えばscriptDef.ktのようなKotlinソースファイルを追加します。

  3. scriptDef.ktでクラスを作成します。これは、このタイプのスクリプトのスーパークラスになるため、abstractまたはopenとして宣言します。

    kotlin
    // abstract (or open) superclass for scripts of this type
    abstract class ScriptWithMavenDeps

    このクラスは、後でスクリプト定義への参照としても機能します。

  4. クラスをスクリプト定義にするには、@KotlinScriptアノテーションでマークします。アノテーションに2つのパラメーターを渡します。

    • fileExtension – このスクリプトタイプのファイル拡張子を定義する、.ktsで終わる文字列です。
    • compilationConfigurationScriptCompilationConfigurationを拡張し、このスクリプト定義のコンパイルの詳細を定義するKotlinクラスです。これは次のステップで作成します。
    kotlin
    // @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()

    このチュートリアルでは、KotlinスクリプトAPIの説明なしに、動作するコードのみを提供します。 詳細な説明付きの同じコードはGitHubで見つけることができます。

  5. 以下に示すように、スクリプトコンパイル構成を定義します。

    kotlin
    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関数は次のとおりです。

    kotlin
    // 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())

    完全なコードはこちらで確認できます。

スクリプトホストを作成する

次のステップはスクリプトホストを作成することです。これはスクリプトの実行を処理するコンポーネントです。

  1. スクリプトホストモジュールで、build.gradle(.kts)dependenciesブロックに依存関係を追加します。

    • スクリプトホストに必要なAPIを提供するKotlinスクリプトコンポーネント
    • 以前に作成したスクリプト定義モジュール
    kotlin
    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
    }
    groovy
    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
    }
  2. モジュール内にsrc/main/kotlin/ディレクトリを作成し、例えばhost.ktのようなKotlinソースファイルを追加します。

  3. アプリケーションのmain関数を定義します。その本体では、スクリプトファイルへのパスという1つの引数があることを確認し、スクリプトを実行します。次のステップで、evalFileという別の関数でスクリプト実行を定義します。今は空で宣言しておきます。

    mainは次のようになります。

    kotlin
    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)
        }
    }
  4. スクリプト評価関数を定義します。ここでスクリプト定義を使用します。型パラメーターとしてスクリプト定義クラスを指定してcreateJvmCompilationConfigurationFromTemplateを呼び出すことで取得します。次に、スクリプトコードとそのコンパイル構成を渡してBasicJvmScriptingHost().evalを呼び出します。evalResultWithDiagnosticsのインスタンスを返すため、それを関数の戻り型として設定します。

    kotlin
    fun evalFile(scriptFile: File): ResultWithDiagnostics<EvaluationResult> {
        val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<ScriptWithMavenDeps>()
        return BasicJvmScriptingHost().eval(scriptFile.toScriptSource(), compilationConfiguration, null)
    }
  5. main関数を調整して、スクリプト実行に関する情報を出力するようにします。

    kotlin
    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}")
                }
            }
        }
    }

完全なコードはこちらで見つけることができます。

スクリプトを実行する

スクリプトホストがどのように動作するかを確認するために、実行するスクリプトと実行構成を準備します。

  1. プロジェクトのルートディレクトリに、以下の内容でhtml.scriptwithdeps.ktsファイルを作成します。

    kotlin
    @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アノテーションの引数で参照されています。

  2. スクリプトホストを起動し、このファイルを実行する実行構成を作成します。

    1. host.ktを開き、main関数に移動します。左側にRunガターアイコンがあります。
    2. ガターアイコンを右クリックし、Modify Run Configurationを選択します。
    3. Create Run Configurationダイアログで、Program argumentsにスクリプトファイル名を追加し、OKをクリックします。

    スクリプトホストの実行構成

  3. 作成した構成を実行します。

スクリプトがどのように実行され、指定されたリポジトリでkotlinx-html-jvmへの依存関係を解決し、その関数の呼び出し結果を出力するかがわかります。

text
<html>
  <body>
    <h1>Hello, World!</h1>
  </body>
</html>

依存関係の解決には、初回実行時に時間がかかる場合があります。その後の実行は、ローカルのMavenリポジトリからダウンロードされた依存関係を使用するため、はるかに速く完了します。

次のステップ

シンプルなKotlinスクリプトプロジェクトを作成したら、このトピックに関する詳細情報を見つけてください。