【Java】spotlessによるフォーマット
作成日
目次
はじめに
ソースコードのフォーマットツールであるspotlessを試してみました。
本稿では基本的にGradle Pluginとして利用し、Javaのコードのフォーマットが中心になりますが、Mavenで使ったり、他の言語をフォーマットしたりすることもできます。
Checkstyle と比較しての spotless のメリット
Javaのコードスタイルに関するツールだとCheckstyleがあります。
しかし、このツールは基本的に単体ではフォーマットの誤りを指摘はしてくれますが、修正まではしてくれません。
私の知っている他の言語のツールは可能な範囲で修正までしてくれるので、それと比べるとCheckstyleの不便さを感じていました。しかし、spotlessは指摘だけでなく、修正までしてくれるので便利です。
また、spotlessはJavaのフォーマットに使うことが一番多そうな気がしますが、かなり多様な種類のファイルのフォーマットが可能です。
例えばYAMLファイルのフォーマットにも対応しています。Checkstyleを使ったプロジェクトはJavaはきちんとフォーマットされているものの、YAMLによる設定ファイルはガタガタ……、ということがありますが、それらもまとめてフォーマットすることもできます。
基本的な使い方
基本的に公式ドキュメントのとおりです。Gradle Pluginとしての使い方を紹介します。
基本的には次のようにGradle plugin(2024年7月12日現在の最新バージョンは7.0.0.BETA1)を依存に追加し、spotlessブロックの中にフォーマットの設定を行います。
この例では、見て分かる通り、JavaとYAMLファイルをフォーマットするような設定をしています。
どのような設定項目があるかは公式ドキュメントにあるためそれを参考にすればよいです。
plugins {
id("com.diffplug.gradle.spotless") version "7.0.0.BETA1"
}
spotless {
java {
// google java formatでフォーマット。引数はgoogle java formatのバージョンを指定
googleJavaFormat('1.22.0').aosp().reflowLongStrings()
formatAnnotations()
}
yaml {
target '**/*.yaml'
jackson()
}
}
Gradleのこのような設定をするとspotlessApply
(spotlessによるフォーマットを行う)、spotlessCheck
(フォーマットは行わず、チェックのみ行う)のようなタスクが追加されるため、./gradlew spotlessApply
でソースコードのフォーマットが可能になります。
また、check
タスクにもタスクが追加されるため、CIなどでは./gradlew check
でも良いと思います。
調査内容
ドキュメントにはいろいろな設定例があるもののそれぞれの設定項目がどのような意味かがよくわからなかったため、調べてみました。
タブのインデント
Google Java Styleはインデントはスペース2文字(Block indentation: +2 spaces)としています。これはやや特徴的なルールであり、Google Java formatを使いつつ、この設定だけ変えたい場合があると思われます。その場合はaosp()
をつければよいです。
aospとは「Android オープンソース プロジェクト」のことらしいですが、そのスタイルだとインデントはスペース4文字になります。
通常のJavaソースが「Android オープンソース プロジェクト」でよいのか? という気もしますが、普通のGoogle Java Styleとaospの違いはインデントとimportの順序だけのようです。
ならこれをつければ良いかな……と思います。
参考
reflowLongStrings
公式の例では
googleJavaFormat('1.8').aosp().reflowLongStrings().formatJavadoc(false).reorderImports(false).groupArtifact('com.google.googlejavaformat:google-java-format')
のようになっています。
reflowLongStringsとはどのような意味なのでしょうか?
例えば、次のような文字列があったとき、
static final String ANOTHER_LONG_STRING =
"This is another long string but this line is under 100 characters "
+ "and this line is also under 100 characters "
+ "but this line is over 100 characters and will not be reformatted to under 100 characters using the intellij plugin but will be reformatted to under 100 characters using the jar.";
reflowLongStringsなしだと文字列の長さがフォーマットされません。(インデントは調整されました)
しかし、reflowLongStringsをつけると、
static final String ANOTHER_LONG_STRING =
"This is another long string but this line is under 100 characters and this line is"
+ " also under 100 characters but this line is over 100 characters and will not be"
+ " reformatted to under 100 characters using the intellij plugin but will be"
+ " reformatted to under 100 characters using the jar.";
のようにフォーマットされました。
なしだと最後の長い行もそのままでしたが、ありだと各行が100文字を超えないように調整されました。
Google Java Styleは「原則一行は100文字以内」(Column limit: 100)としているため、基本的にreflowLongStringsはつけて調整してもらうのが良いではないかと思います。
参考
- Google Java Format doesn’t reflow long strings
- Formatting code with intellij plugin and using the jar gives different results
細かい設定をする場合
googleJavaFormat()
はメソッドチェーンでいくつかの設定をできますが、個別のルールを細かく調整することはおそらくできないのではないかと思います。
Google Java formatを使いたいが、細かいカスタマイズもしたい場合どうすればよいかというと、googleJavaFormat()
を直接使わず、eclipse jdtによるフォーマットを選択し、その設定ファイルで調整すれば実現できそうです。
Gradleは次のような設定にします。
java {
// 現在は4.32が最新と思われる
eclipse('4.32').configFile('config/eclipse-prefs.xml')
}
そして、configフォルダにeclipse jdf formatの設定ファイルを配置します。
eclipse jdtの知識はまったくないのですが、google/style guideのXMLを使えば良さそうです。
これを配置し、適宜修正します。例えばインデントを調整する場合はorg.eclipse.jdt.core.formatter.tabulation.size
のvalue
を4にすればスペース4文字によるインデントになりました。
Checkstyleの設定を使う
すでにCheckstyleを使っている場合その設定を流用したいことがあるかもしれません。
しかし、Checkstyleの設定ファイルはeclipse jdtのものともまた違います。
Issueによると
Nope. Checkstyle is for warning about problems, Spotless focuses on automatically fixing problems. There are lots of things that you can warn about but can’t automatically fix, so the thing you are asking for will probably never happen.
Is there a tool to convert the checkstyle configuration file to the spotless configuration file
Checkstyleは役割が違うため、Checkstyleの設定をspotlessの設定に変換することは単純にはできないようですし、今後もできるようにならないようです。
すでに高度にカスタマイズされたCheckstyleの設定がある場合、頑張って1つずつeclipse jdt用の設定ファイルに置き換えるしかないと思われます。
動作確認リポジトリ
spring-kafka-demoというリポジトリでspotlessを試しました。
masterブランチはgoogleJavaFormatでフォーマットされていますが、eclipseブランチはeclipseでフォーマットされています。