mavenプロジェクトでフォーマッターを使う

技術Tipsです。

概要としてはmavenを利用しているspring bootプロジェクトにおいてコードフォーマットを行う方法、及びそれをIDE(Eclipse, IntelliJ)に適用する方法になります。

背景

コードフォーマッターが必要になった経緯です。

最近は仕事でSpring Bootを使ってWebアプリの開発をしています。Javaの開発であればEclipseIntelliJなど優秀なIDEがあるため、コマンド一発でフォーマットしてくれます。便利ですよね。

なので、個別にフォーマッターを入れる必要は開発時点ではなかったのですが、CI/CD時にフォーマットチェックを入れたいという話になり、Githubなどに上げたあとの環境でフォーマットをかける必要が出てきました。

今回はmavenでプロジェクトを作っていたためmavenでのフォーマッターの導入の話、IDEと共通のフォーマッターを使用する方法などを書きます。

使用するフォーマッター

formatter-maven-pluginというのを利用します。が、公式らしきサイトのUsageを試していてもうまくいかず、少し自分で調べる必要がありました。

利用方法

公式サイトの方ではpom.xmlに書くpluginと、実行方法は以下のようになっていました

pom.xml

<project ...>
    ...
    <plugins>
      <plugin>
        <groupId>net.revelc.code.formatter</groupId>
        <artifactId>formatter-maven-plugin</artifactId>
        <version>2.0.2-SNAPSHOT</version>
      </plugin>
    </plugins>
    ...
</project>

実行方法

mvn java-formatter:format

しかしこの方法ではフォーマットはおろか、プラグインの実行すらされません。 というかそもそもmvn java-formatter:formatで実行しているjava-formatterプラグインのprefixから検索しているのにプラグインのartifactIdがformatter-maven-pluginだし。。。

色々調べたり試したりしたところ、下記のプラグイン指定と実行方法で行けました。

pom.xml

<project ...>
    ...
    <plugins>
      <plugin>
        <groupId>net.revelc.code.formatter</groupId>
        <artifactId>formatter-maven-plugin</artifactId>
        <version>2.0.1</version>
      </plugin>
    </plugins>
    ...
</project>

実行方法

mvn formatter:format -Dconfigfile=formatter.xml

formatter.xmlは下で説明しますが、フォーマット用の設定ファイルです。

フォーマットチェックとフォーマット

対象ファイル

確認のため、あえてフォーマットが崩れているファイルを用意しました。main関数を1行で記述しています。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MavenFormatterDemoApplication{
    public static void main(String[] args){ SpringApplication.run(MavenFormatterDemoApplication.class, args);}
}

設定ファイルの取得

上で述べた設定用のxmlファイルですが、今回はSpring bootで標準的に使われているらしいxmlファイルを落としてきて入れました。formatter-maven-pluginではeclipseのフォーマット用のxmlが設定ファイルとして使え、検索するといくつかヒットします。

github.com

設定の例

下記は今回使用した設定ファイルの一例です。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="12">
<profile kind="CodeFormatterProfile" name="Spring Boot Java Conventions" version="12">
...
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
...
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="90"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
...
</profile>
</profiles>

設定項目はたくさんありますが、<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="90"/>(改行する文字数)のように比較的理解しやすいものが多いです。

とはいえ直接編集するのは骨が折れるので、カスタマイズするなら後述するEclipseの設定を用いてxmlを生成するのがよいでしょう。

フォーマットチェックとフォーマット

設定したxmlファイルのフォーマットに従っているかどうかをチェックするには以下のコマンドを実行します。

mvn formatter:validate -Dconfigfile=formatter.xml

先程のようにフォーマットが崩れているファイルがプロジェクトに存在すると、mavenがエラーを吐きます。

> ~/maven-formatter-demo> mvn formatter:validate -Dconfigfile=formatter.xml
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven-formatter-demo 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- formatter-maven-plugin:2.0.1:validate (default-cli) @ maven-formatter-demo ---
[INFO] Using 'UTF-8' encoding to format source files.
[INFO] Number of files to be formatted: 2
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.130 s
[INFO] Finished at: 2017-10-01T19:57:48+09:00
[INFO] Final Memory: 13M/81M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal net.revelc.code.formatter:formatter-maven-plugin:2.0.1:validate (default-cli) on project maven-formatter-demo: File '~/maven-formatter-demo/src/main/java/com/yoghurt1131/mavenformatterdemo/MavenFormatterDemoApplication.java' format doesn't match! -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

では、これをフォーマットしていきます。先程のmvnコマンドでvalidateとしていた箇所をformatに変えるだけです。

 mvn formatter:format -Dconfigfile=formatter.xml
> ~/mave-formatter-demo> mvn formatter:format -Dconfigfile=formatter.xml
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building mave-formatter-demo 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- formatter-maven-plugin:2.0.1:format (default-cli) @ mave-formatter-demo ---
[INFO] Using 'UTF-8' encoding to format source files.
[INFO] Number of files to be formatted: 2
[INFO] Successfully formatted:          1 file(s)
[INFO] Fail to format:                  0 file(s)
[INFO] Skipped:                         1 file(s)
[INFO] Read only skipped:               0 file(s)
[INFO] Approximate time taken:          0s
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.129 s
[INFO] Finished at: 2017-10-01T20:00:00+09:00
[INFO] Final Memory: 14M/79M
[INFO] ------------------------------------------------------------------------

フォーマット成功ファイルの数、失敗したファイルの数、スキップされた(すでにフォーマットされていた)ファイルの数などがでます。

実際に確認してみると、きちんとフォーマットがされています。

フォーマット前

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MavenFormatterDemoApplication{
    public static void main(String[] args){ SpringApplication.run(MavenFormatterDemoApplication.class, args);}
}

フォーマット後

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MavenFormatterDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(MavenFormatterDemoApplication.class, args);
    }
}

IDEでの利用

作成したフォーマッターを使えば、PaaS環境などのIDEが無い場所でもフォーマットチェックやフォーマットが行えるようになりました。とはいえ、IDEのフォーマッターとmavenで使用するフォーマッターが違ってしまうと、開発環境でかけたフォーマットがpush先で通らないといった事故が起きる可能性があります。

ここでは、作成したフォーマッターを各IDE(eclipse, IntelliJ)に読み込む方法を書きます。

eclipseでの利用

Eclipse->Preferences(設定)->Java->Code Style->Formatterに設定項目があります。

f:id:yoghurt1131:20171001202002p:plain:w500

ここでxmlファイルをimportすることができます。

また、Newから独自のフォーマット規約を作成することができます。これはxmlファイルとしてExportすることができるので、既存のがイマイチで自分でフォーマッターを作りたいという場合はこれを利用してオリジナルのフォーマッターを作成するのがいいかと思います。

IntelliJでの利用

IntelliJでも利用方法はほとんど同じです。

IntelliJ->Preferences->Editor->Code Style->JavaからImport Schemeをすることで設定ファイルを導入することができます。

注意点としては、IntelliJにはIntelliJ独自のコードフォーマット(IntelliJ IDE code style XML)があることです。

Eclipseとの互換性はあるため、Eclipseで作ったxmlファイルをIntelliJで利用することはできますが、逆はできません。開発時にIntelliJの設定でフォーマッターを作成した場合はそのままmavenで使用することができないのでご注意ください。

リンク・参考