以下の内容はhttps://blog1.mammb.com/entry/2025/12/02/180648より取得しました。


Error Prone で Java コンパイラを強化する


Error Prone is 何?

  • Google がオープンソース化(2012年)した Java コンパイラプラグイン
  • SonarQube、FindBugs/SpotBugs などと同様の静的解析ツール
  • コードの抽象構文木(AST)を解析し、バグやアンチパターンを特定する
  • javac に直接フックし、バグやアンチパターンをコンパイルエラー/警告として報告
  • 可能な場合は修正提案を含むパッチファイルを生成し、オプションで変更をコードベースに適用できる
  • 独自のバグチェックを作成して拡張できる

リポジトリは以下になります

github.com


他の静的解析ツールとの大きな違いは、javac のプラグインとなっているため、javac を拡張したように動作する点です。

public class ErrorProneJavacPlugin implements Plugin {
  @Override
  public String getName() {
    return "ErrorProne";
  }

  @Override
  public void init(JavacTask javacTask, String... args) {
    BaseErrorProneJavaCompiler.addTaskListener(
        javacTask, BuiltInCheckerSuppliers.defaultChecks(), ErrorProneOptions.processArgs(args));
  }
}

バグパターンにマッチする場合、コンパイル・エラーとなります。

その他、独自のチェックを追加したり、サードパーティ製のルールを追加したりすることもできます。例えば、NullAway で Java をヌルセーフにしたり。


Error Prone の導入

Gradle で利用する場合は、サードパーティからプラグインgradle-errorprone-pluginが公開されているので、これを利用できます。

build.gradle.kts を以下のようにして導入します。

plugins {
    java
    id("net.ltgt.errorprone") version "4.3.0"
}

repositories {
    mavenCentral()
}

dependencies {
    errorprone("com.google.errorprone:error_prone_core:2.45.0")
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

導入は以上で完了です。


Error Prone の動作

例えば、以下のような(例外のインスタンス化のみ行い、throw を忘れている)コードがあった場合、

  if (args.length > 0 && args[0].isEmpty()) {
    new IllegalArgumentException();
  }

ビルドでコンパイルエラーとなります。

$ gradlew build
...
  Foo.java:13: error: [DeadException] Exception created but not thrown
              new IllegalArgumentException();
              ^
      (see https://errorprone.info/bugpattern/DeadException)
    Did you mean 'throw new IllegalArgumentException();'?


例えば以下のようなコードも、

  Set<Short> s = new HashSet<>();
  for (short i = 0; i < 100; i++) {
      s.add(i);
      s.remove(i - 1);
  }

以下のようにコンパイルエラーとなります。

$ gradlew build
...

  Foo.java:21: error: [CollectionIncompatibleType] Argument 'i - 1' should not be passed to this method; its type int is not compatible with its collection's type argument Short
              s.remove(i - 1);
                      ^
      (see https://errorprone.info/bugpattern/CollectionIncompatibleType)

Bug patterns は大量にあり https://errorprone.info/bugpatterns にまとまっています。

まぁ、IDE 使っていれば大抵は警告表示してくれるので、ありがたみは少ないですが、コンパイルエラーとして修正が強制される点がメリットでしょうか。


チェックの抑止

該当箇所以下のようにアノテーションを付けることで、チェックを抑止することができます。

@SuppressWarnings("CollectionIncompatibleType")
public void foo() {
  Set<Short> s = new HashSet<>();
  for (short i = 0; i < 100; i++) {
      s.add(i);
      s.remove(i - 1);
  }
  ...
}

特定の箇所だけでなく、コードベース全体でチェックの有効/無効を切り替えたり、警告とするかエラーとするかなどを切り替えることもできます。

コマンドラインオプション(-Xep:<checkName>[:severity])を利用します(severity には OFF WARN ERROR を指定します)。

例えば ReferenceEquality を無効にするには以下のようにコマンドラインオプションを指定します。

-Xep:ReferenceEquality:OFF

ReferenceEquality を警告表示に変更するには以下のようにします。

-Xep:ReferenceEquality:WARN


特定のチェックではなく、全体を一括で指定するコマンドラインオプションも用意されています。

  • -XepDisableAllChecks : 全てのチェックを完全に無効化する
  • -XepDisableAllWarnings : 全ての警告を無効化する(エラーレベルの報告はそのまま)
  • -XepDisableWarningsInGeneratedCode : @Generatedなどが付いた自動生成されたコードの警告を無効化する
  • -XepAllErrorsAsWarnings : ERROR を WARNING として扱う(コンパイルは成功する)
  • -XepAllSuggestionsAsWarnings : SUGGESTION(スタイル改善など)を WARNING として報告する
  • -XepAllDisabledChecksAsWarnings : デフォルトで無効化されているチェックを有効化し WARNING として報告する

これらのオプションは Gradle プラグイン側で設定することもできます。

import net.ltgt.gradle.errorprone.errorprone

//...

tasks.withType<JavaCompile>().configureEach {
    options.errorprone.disableAllChecks = true
    options.errorprone.disableWarningsInGeneratedCode = true
}






以上の内容はhttps://blog1.mammb.com/entry/2025/12/02/180648より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14