👏

GradleでCheckStyleを利用する

2021/04/30に公開

概要

コードレビューで瑣末なことに時間を割かれるのが辛いので機械的にチェックしたい。
以前からCheckStyleは導入していたけど、雰囲気で使っている状態でした。
これではいかんなと、一念発起して環境構築から始めてみたところ、環境構築からハマりました。
環境構築手順を残しておきます。

TL;DR

Gradleプラグインの設定でCheckStyleの最新バージョンを指定しましょう。

前提条件

Gradle 6.8

GradleへCheckStyleを導入する

プラグインが提供されているのでこちらを利用します。
https://docs.gradle.org/current/userguide/checkstyle_plugin.html

plugins {
    id 'checkstyle'
}

CheckStyle定義を用意する

サンプルのCheckStyle定義ファイルはGoogle Styleを利用します。
https://checkstyle.sourceforge.io/google_style.html
CheckStyle公式サイトで紹介されています。
https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml

以下のように配置します。

config/
└── checkstyle
    └── checkstyle.xml

サンプルコードを用意する

適当なコードを書いて配置します。

public class Sample {
  public static void Main(String[] args) throws Exception {

  }
}
src/main/
├── java
│   └── Sample.java
└── resources

実行してみる

$ ./gradlew build
> Task :checkstyleMain FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':checkstyleMain'.
> Unable to create Root Module: config {

なぜか失敗してしまいました。
CheckStyleはモジュールで構成されており、それが作成できなかったと怒られています。

スタックトレースを確認します。

$ ./gradlew build --stacktrace
〜超絶長いので省略〜
Caused by: com.puppycrawl.tools.checkstyle.api.CheckstyleException: 'RecordComponentName' クラスをインスタンス化できませんでした。また、以下のクラス名でもインスタンス化できませんでした .RecordComponentName, RecordComponentNameCheck, .RecordComponentNameCheck 。 クラス名を正規名で指定しているか再確認してください。または、単純名の使用を設定する方法 https://checkstyle.org/config.html#Packages をお読みください。 また、Checker に渡されているクラスローダが正しく設定されているか再確認してください。
        at com.puppycrawl.tools.checkstyle.PackageObjectFactory.createModule(PackageObjectFactory.java:215)
        at com.puppycrawl.tools.checkstyle.TreeWalker.setupChild(TreeWalker.java:116)
        ... 255 more

RecordComponentNameの設定に問題がありそうです。
公式サイトを確認します。
https://checkstyle.sourceforge.io/config_naming.html#RecordComponentName

since 8.40

Gradleのバージョンいくつやねんってことで依存関係を確認します。

$ ./gradlew dependencies | grep checkstyle
Root project 'checkstyle-example'
checkstyle - The Checkstyle libraries to be used for this project.
\--- com.puppycrawl.tools:checkstyle:8.37

最新版が入ってないという、あるあるな原因でした。

CheckStyleの最新バージョンを使うようにする

Gradleにデフォルトで入ってるバージョンは8.37です。
以下で定義されていました。
https://github.com/gradle/gradle/blob/5ec3f672ed600a86280be490395d70b7bc634862/subprojects/docs/src/snippets/dependencyManagement/catalogs-settings/groovy/settings.gradle#L48

定期的にバージョンアップしているみたいなので、待つか、最終手段としてPRを投げることも考えられます。
が、ちょっと落ち着いてプラグインのリファレンスを確認します。
https://docs.gradle.org/current/dsl/org.gradle.api.plugins.quality.CheckstyleExtension.html

toolVersion	
The version of the code quality tool to be used.

エラーメッセージでググってもこのパラメータに言及されているドキュメントは見当たりませんでしたが、こちらでCheckStyleのバージョンが制御できるみたいです。

build.gradleに追加します。

checkstyle {
    toolVersion = '8.42'
}
$ ./gradlew dependencies | grep checkstyle
Root project 'checkstyle-example'
checkstyle - The Checkstyle libraries to be used for this project.
\--- com.puppycrawl.tools:checkstyle:8.42
$ ./gradlew build

> Task :checkstyleMain
[ant:checkstyle] [WARN] /Users/sasakitakashi/checkstyle-example/src/main/java/Sample.java:1:1: Javadoc コメントがありません。 [MissingJavadocType]
[ant:checkstyle] [WARN] /Users/sasakitakashi/checkstyle-example/src/main/java/Sample.java:2:22: Method name 'Main' must match pattern '^[a-z][a-z0-9][a-zA-Z0-9_]*$'. [MethodName]
Checkstyle rule violations were found. See the report at: file:///Users/sasakitakashi/checkstyle-example/build/reports/checkstyle/main.html
Checkstyle files with violations: 1
Checkstyle violations by severity: [warning:2]


BUILD SUCCESSFUL in 2s
3 actionable tasks: 1 executed, 2 up-to-date

GOOD!

おわりに

以上、GradleへCheckStyleを導入するときに得た知見のシェアでした。
カスタムチェック作ったりしてDeveloperExperienceを改善したいと思います。

Discussion