職場のプロジェクトがメインで指定する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では安全側に倒しているというところでしょうか…。
以上