Gradle Kotlin Scriptの現状を見てみる

## はじめに
Gradle Kotlinとは、KotlinのDSLでGradleのスクリプトをかけるというものになります。
GradleスクリプトをKotlinでかけると、何が良いかという点については公式ではこんな感じで紹介されています。

- 自動補完とコンテンツアシストが使用できる
- クイックドキュメンテーション
- ソースのハイライト
- リファクタリングなどなど

Groovyから、Kotlinにしたほうが幸せなことは多そうです。
ただ、後述しますがまだこの恩恵を受けられるのはまだ1部の人のみとなります。

- [Gradle Meets Kotlin - Kotlin Blog](https://blog.jetbrains.com/kotlin/2016/05/gradle-meets-kotlin/)
- [Kotlin Meets Gradle - Gradle](https://blog.gradle.org/kotlin-meets-gradle)
- [GitHub リポジトリ](https://github.com/gradle/gradle-script-kotlin)

## 実際に触ってみる

IntelliJ IdeaでまずはKotlinのバージョンを1.1にあげます。
KotlinのEarly Accessを使用します。手順はざっとこんな感じです。

1. IntelliJ内の適当な場所で`Cmd + Shift + A`コマンドを使ってメニューを表示させる
2. `Configure Kotlin Plugin Updates`を選択して
3. `Early Access Preview1.1`を選択して、OKを押してアップデートします
4. 再起動しましょう

まずはGradleを初期化しつつ、GradleKotlin用のbuildファイルを作成します。
Gradleのバージョンは、3.0以上かをチェックしておいてください。

```
$ gradle init
$ touch build.gradle.kts
```

settings.gradleを編集して、以下の行を足します。

```settings.gradle
rootProject.buildFileName = 'build.gradle.kts'
```

ここで、一旦準備は整いました。
では、実際にコードを動かしたいと思います。
まずは、既存のJavaの"Hellow World"をサンプル通り動かしてみたいと思います。

ソースフォルダの下に、いつも通りにこんな感じのJavaファイルを作成します。

```src.main.java.samples.HelloWorld.java
package samples;

public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("Hello, world!");
    }
    
}
```

次に、`build.gradle.kts`ファイルを編集します。
※ハイライトがきかないのと、IDEから大量のお叱りを受けると思いますが無視してください

```build.gradle.kts
import org.gradle.api.plugins.*
import org.gradle.api.tasks.wrapper.*
import org.gradle.script.lang.kotlin.*

apply<ApplicationPlugin>()

configure<ApplicationPluginConvention> {
    mainClassName = "samples.HelloWorld"
}

repositories {

}

dependencies {

}
```

では、実際に動かしてみます。
コンソールで以下のように打つと、Hello, Worldと表示されるのが分かると思います。

```
$ ./gradlew run

:compileJava
:processResources UP-TO-DATE
:classes
:run
Hello, world!

BUILD SUCCESSFUL

Total time: 2.856 secs
```

どうやら、ハイライトや自動補完などはIntelliJのバージョンやUltimateバージョンなのかによって、サポートがきくかきかないかが決まってくるようです。
現状では、残念ながら当初の触れ込みにあったらメリットはあまりない状態と言えます。。。

## 気になるAndroidのスクリプトファイル

AndroidでKotlinを使用している人が多いと思うので、実際にAndroid用に使用した際にどうなるのかも見てみたいと思います。
こちらは、サンプルのリポジトリから引用しました。

スクリプトを見てみると、まずAndroid関係のimport文が増えていることが分かると思います。
また、`android`タグなど、普段と見た目を揃えるためにスクリプトの最後の方で多くのExtentionを定義しています。
ココらへんは今後、公式でAndroidサポートがされれば快適になりそうだなと思いました。

```
import com.android.build.gradle.AppExtension
import com.android.build.gradle.AppPlugin
import com.android.build.gradle.internal.dsl.BuildType
import com.android.builder.core.DefaultApiVersion
import com.android.builder.core.DefaultProductFlavor
import com.android.builder.model.ApiVersion

import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project

import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper

import java.lang.System

buildscript {
    //Temporary hack until Android plugin has proper support
    System.setProperty("com.android.build.gradle.overrideVersionCheck",  "true")

    repositories {
        jcenter()
        gradleScriptKotlin()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:2.2.0")
        classpath(kotlinModule("gradle-plugin"))
    }
}

repositories {
    jcenter()
    gradleScriptKotlin()
}


apply {
    plugin<AppPlugin>()
    plugin<KotlinAndroidPluginWrapper>()
}

android {
    buildToolsVersion("23.0.3")
    compileSdkVersion(23)

    defaultConfigExtension {
        setMinSdkVersion(15)
        setTargetSdkVersion(23)

        applicationId = "com.example.kotlingradle"
        versionCode = 1
        versionName = "1.0"
    }

    buildTypesExtension {
        release {
            isMinifyEnabled = false
            proguardFiles("proguard-rules.pro")
        }
    }
}

dependencies {
    compile("com.android.support:appcompat-v7:23.4.0")
    compile(kotlinModule("stdlib"))
}

//Extension functions to allow comfortable references
fun Project.android(setup: AppExtension.() -> Unit) = the<AppExtension>().setup()

fun NamedDomainObjectContainer<BuildType>.release(setup: BuildType.() -> Unit) = findByName("release").setup()

fun AppExtension.defaultConfigExtension(setup: DefaultProductFlavor.() -> Unit) = defaultConfig.setup()

fun AppExtension.buildTypesExtension(setup: NamedDomainObjectContainer<BuildType>.() -> Unit) = buildTypes { it.setup() }

fun DefaultProductFlavor.setMinSdkVersion(value: Int) = setMinSdkVersion(value.asApiVersion())

fun DefaultProductFlavor.setTargetSdkVersion(value: Int) = setTargetSdkVersion(value.asApiVersion())

fun Int.asApiVersion(): ApiVersion = DefaultApiVersion.create(this)
```

## おわりに

少し駆け足のものとなってしまいましたが、簡単にgradle-kotlin-scriptのことが伝わればと思います。
ただ、まだAndroidStudioではIntelliJのバージョンなどもあり、使えなかったりと導入にはしばらくまだ時間がかかると思いますが、型のある形でGradleのScriptをかけると色々とよいことがありそうです。

期待して待ちましょう。