eclipseがメインのIDEに指定されているプロジェクトでIntelliJを使って開発する
職場のプロジェクトがメインで指定するIDEはeclipseですが、IntelliJ IDEAが大好きなのでIntelliJ IDEAで仕事しています。
するとどうしても問題が出てきます。
- importの順番が異なるために無駄なdiffが出てくる
- コードスタイルが異なるのでレビューしづらい
- インスペクションのレベルが違うのでレビューしづらい/チェックしづらい
importの順番
importの順番は気合で直します(嘘)
eclipseからコードスタイルフォーマットを出力してIntelliJで取り込んでもImportの順番は出力できないようです。
したがって下のQiitaの記事を参考に Code Style > Java > Impors > Import Layout にてImportの順番をeclipseのそれに合わせます。
しかし、時折ですが、eclipseで書いたコードのimport順がおかしな場合もあります。そのようなイレギュラーケースは気合で直していたりします。
コードスタイル
上記の通りeclipseからコードフォーマット設定をxmlで出力して、取り込むことで対応します。しかしeclipseのデフォルト設定で開発している場合などはxmlの情報が少なくなり、かなり変なスタイルが取り込まれることもあったり、そもそもコードスタイルをxmlで出力していないということもあります(.settings/org.eclipse.jdt.core.prefs で管理している場合など)。
この場合はeclipseのフォーマッタをターミナルから起動して修正します。
$ ~/path/to/Eclipse.app/Contents/MacOS/eclipse -application org.eclipse.jdt.core.JavaCodeFormatter -verbose -config ~/path/to/setting/org.eclipse.jdt.core.prefs ~/path/to/project/src/main/java/com/example/Foo.java
なお、以前はこれをgit statusと組み合わせてgit commitのフックで実行していましたが、IntelliJのchangelistが壊れるのでやめて、次のスクリプトを利用してpushの前に実行するようにしています。
#!/usr/bin/env bash
project=~/path/to/project
eclipse=~/path/to/Eclipse.app/Contents/MacOS/eclipse
cd ${project}
head=`git log --oneline --decorate | grep HEAD | awk '{printf $1}'`
last=`git log --oneline -decorate` | grep origin | awk '{printf $1}'`
java_files=`git diff --name-only ${head} ${last} | awk -v dir=${project} '{print dir"/"$1}' awk -F\| 'system("test -f " $1)==0 { print $1 }'`
${eclipse} -application org.eclipse.jdt.core.JavaCodeFormatter -verbose -config ~/path/to/setting/org.eclipse.jdt.core.prefs ${java_files}
git add ${java_files}
git commit -m 'apply eclipse formatter'
コードインスペクション
これが一番困っています。eclipseとIntelliJで警告になるレベルが異なる(IntelliJでは設定可能)ようです。下手に警告がちらつくと重要な警告を発見できなかったり、レビューに集中できなかったりと弊害が大きいです。
いろいろと方法を考えたのですが、とりあえずecjでコンパイルするのが一番よさそうです。
apply plugin: 'java' configurations { eclipse } dependencies { eclipse 'org.eclipse.jdt.core.compiler:ecj:4.4' // 他省略 } task ecj(type: JavaExec) { main = 'org.eclipse.jdt.internal.compiler.batch.Main' classpath configurations.eclipse.asPath args '-encoding', 'utf8' args '-source', '8' args '-d', "$buildDir/ecj" args '-target', '8' args '-cp', configurations.compileClasspath.asPath args sourceSets.main.allJava }
このようなタスクを記述した ecj.gradle ファイルを作って、 ./gradlew -b ecj.gradle ecj を起動することで警告を探してeclipseに合わせたコードを記述します。
出力例
15. WARNING in /path/to/project/src/main/java/org/mikeneck/util/Last.java (at line 143)
.<Last<T>>map(Candidate::new)
^^^^^^^^^^^^^^
Type safety: The constructor Candidate(Object) belongs to the raw type Candidate. References to generic type Candidate<T> should be parameterized
----------
16. WARNING in /path/to/project/src/main/java/org/mikeneck/util/Last.java (at line 147)
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Unsupported @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
----------
例えば、上の出力例ではIntelliJでは Optional をフィールドまたはパラメーターに利用すると警告が出てくるので @SuppressWarnings("OptionalUsedAsFieldOrParameterType") をつけますが、eclipseでは OptionalUsedAsFieldOrParameterType に対応していないので警告になっています(Optional をフィールドまたはパラメーターに使っても警告が出ないのだろうか…詳しい人教えて…)。またeclipseでは推論可能な型パラメーターを省略すると警告が出てしまうようです(Foo<T> のコンストラクタを Foo::new と書くと警告が出るが、 Foo<T>::new と書くと警告が出ない。一方IntelliJでは推論可能な型パラメーターの省略を推奨している)。おそらく言語仕様で曖昧に解釈できる箇所をecjでは安全側に倒しているというところでしょうか…。
以上