Kotlintを試す
導入手順は公式に書いてある通り。gradleでしたら警告してくれます。
./gradlew ktlint :ktlint /Users/****/Develop/git/ddd-sample-kotlin/src/main/kotlin/work/doilux/dddsamplekotlin/ftth/order/OrderService.kt:3:24: Unnecessary block ("{}") /Users/****/Develop/git/ddd-sample-kotlin/src/main/kotlin/work/doilux/dddsamplekotlin/ftth/order/OrderService.kt:4:1: Unexpected blank line(s) before "}" /Users/****/Develop/git/ddd-sample-kotlin/src/test/kotlin/work/doilux/dddsamplekotlin/DddSampleKotlinApplicationTests.kt:12:1: Unexpected indentation (1) (it should be 4) /Users/****/Develop/git/ddd-sample-kotlin/src/test/kotlin/work/doilux/dddsamplekotlin/DddSampleKotlinApplicationTests.kt:15:1: Unexpected blank line(s) before "}" :ktlint FAILED
指摘事項を直して再実行するとエラーが消えました。
./gradlew ktlint :ktlint BUILD SUCCESSFUL
カスタムルールを作る
「性別を表すクラスであの単語を使うな」というルールを作ってみる。
package work.doilux.dddsamplekotlin.ftth.order import java.time.LocalDate data class Customer( val firstName: FirstName, val lastName: LastName, val birthDay: BirthDay, val sex: Sex ) data class FirstName(val value: String) data class LastName(val value: String) data class BirthDay(val value: LocalDate) enum class Sex { MALE, FEMALE, ETC }
テンプレートをゲットする
ktlintコマンドを使ってパースする
必須ではないけど、実装とデバッグがしやすいため。手順は公式に書いてるので割愛。
Ruleを書く
テンプレートにあるNoVarRule.ktを参考に実装していけば良さそう。Ruleインターフェースを実装して、visitメソッドをオーバーライドすればいいようです。引数はこんな感じ。
key | value |
---|---|
node | AST node 前述のステップでパースした結果の1行だと思う |
autoCorrect | indicates whether rule should attempt auto-correction ktlintには自動的に修正する機能があるっぽい。その機能を使うかどうか(今回は対応しない) |
emit | a way for rule to notify about a violation (lint error) 違反があった場合の通知メソッド |
NoVarRuleを軽く解説しておくと。
override fun visit( node: ASTNode, autoCorrect: Boolean, emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit ) { if (node is LeafPsiElement && node.textMatches("var") && getNonStrictParentOfType(node, KtStringTemplateEntry::class.java) == null) { emit(node.startOffset, "Unexpected var, use val instead", false) } }
node is LeafPsiElement
は意味そのままで、「リーフエレメントのとき」、node.textMatches("var")
もそのまま「"var"と一致するとき」という条件式。
getNonStrictParentOfType
はKtStringTemplateEntry
型の親ノードを取得しています。ここでは== null
という条件なので、取得できないときに真という条件。これが意味するのは、例えばvar str = "var"
のとき、文字リテラルの"var"はチェック対象外ってことです。
ということで実装しました。
class NoSexRule : Rule("no-sex") { override fun visit( node: ASTNode, autoCorrect: Boolean, emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit ) { if (node is LeafPsiElement && (node.textMatches("sex") || node.textMatches("Sex") || node.textMatches("SEX")) && getNonStrictParentOfType(node, KtStringTemplateEntry::class.java) == null) { emit(node.startOffset, "Unexpected word, use gender instead", false) } } }
テストもあります(ここでは割愛) 実装終わったらRuleSetProviderに追加します。
class CustomRuleSetProvider : RuleSetProvider { override fun get(): RuleSet = RuleSet("custom", NoVarRule(), NoSexRule()) }
kotlinコマンドで試す
まずはjarに固めます。
./gradlew clean jar
公式にある通り、-Rでjarファイルを指定したらちゃんと検出してくれました。
kotlint -R /Users/xxxx/Develop/git/ddd-sample-kotlin/ktlint/rules/ktlint-ruleset-template.jar src/**/*kt /Users/xxxx/Develop/git/ddd-sample-kotlin/src/main/kotlin/work/doilux/dddsamplekotlin/ftth/order/Customer.kt:9:13: Unexpected word, use gender instead /Users/xxxx/Develop/git/ddd-sample-kotlin/src/main/kotlin/work/doilux/dddsamplekotlin/ftth/order/Customer.kt:9:18: Unexpected word, use gender instead /Users/xxxx/Develop/git/ddd-sample-kotlin/src/main/kotlin/work/doilux/dddsamplekotlin/ftth/order/Customer.kt:15:12: Unexpected word, use gender instead
gradleで試す
前述のjarファイルを$PROJECT_ROOT/ktlint/roles配下に配置して、build.gradleを以下のようにすると、gradleのタスクからチェックできました。
task ktlint(type: JavaExec, group: "verification") { description = "Check Kotlin code style." classpath = configurations.ktlint main = "com.github.shyiko.ktlint.Main" args "-R", "ktlint/rules/ktlint-ruleset-template.jar", "src/**/*.kt" }
./gradlew ktlint :ktlint /Users/xxxx/Develop/git/ddd-sample-kotlin/src/main/kotlin/work/doilux/dddsamplekotlin/ftth/order/Customer.kt:9:13: Unexpected word, use gender instead /Users/xxxx/Develop/git/ddd-sample-kotlin/src/main/kotlin/work/doilux/dddsamplekotlin/ftth/order/Customer.kt:9:18: Unexpected word, use gender instead /Users/xxxx/Develop/git/ddd-sample-kotlin/src/main/kotlin/work/doilux/dddsamplekotlin/ftth/order/Customer.kt:15:12: Unexpected word, use gender instead :ktlint FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':ktlint'. > Process 'command '/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1 * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. BUILD FAILED Total time: 4.349 secs