PicnicSupermarket / error-prone-support

Error Prone extensions: extra bug checkers and a large battery of Refaster rules.
https://error-prone.picnic.tech
MIT License
199 stars 39 forks source link
abstract-syntax-tree ast automatic-refactoring code-quality code-style code-transformation error-prone hacktoberfest java refactoring refactoring-tools refaster static-analysis
Error Prone Support logo

Error Prone Support

Error Prone Support is a Picnic-opinionated extension of Google's Error Prone. It aims to improve code quality, focussing on maintainability, consistency and avoidance of common pitfalls.

Error Prone is a static analysis tool for Java that catches common programming mistakes at compile-time.

To learn more about Error Prone (Support), how you can start using Error Prone in practice, and how we use it at Picnic, watch the conference talk Automating away bugs with Error Prone in practice. Also consider checking out the blog post Picnic loves Error Prone: producing high-quality and consistent Java code.

Maven Central Reproducible Builds OpenSSF Best Practices OpenSSF Scorecard CodeQL Analysis GitHub Actions Mutation tested with PIT Quality Gate Status Maintainability Rating Reliability Rating Security Rating Coverage Duplicated Lines (%) Technical Debt License PRs Welcome

Getting startedDeveloping Error Prone SupportHow it worksContributing


⚡ Getting started

Installation

This library is built on top of Error Prone. To use it, read the installation guide for Maven or Gradle below. The library requires that your build is executed using JDK 17 or above, but supports builds that target older versions of Java.

Maven

  1. First, follow Error Prone's installation guide.
  2. Next, edit your pom.xml file to add one or more Error Prone Support modules to the annotationProcessorPaths of the maven-compiler-plugin:

    <build>
       <pluginManagement>
           <plugins>
               <plugin>
                   <groupId>org.apache.maven.plugins</groupId>
                   <artifactId>maven-compiler-plugin</artifactId>
                   <!-- Prefer using the latest release. -->
                   <version>3.12.0</version>
                   <configuration>
                       <annotationProcessorPaths>
                           <!-- Error Prone itself. -->
                           <path>
                               <groupId>com.google.errorprone</groupId>
                               <artifactId>error_prone_core</artifactId>
                               <version>${error-prone.version}</version>
                           </path>
                           <!-- Error Prone Support's additional bug checkers. -->
                           <path>
                               <groupId>tech.picnic.error-prone-support</groupId>
                               <artifactId>error-prone-contrib</artifactId>
                               <version>${error-prone-support.version}</version>
                           </path>
                           <!-- Error Prone Support's Refaster rules. -->
                           <path>
                               <groupId>tech.picnic.error-prone-support</groupId>
                               <artifactId>refaster-runner</artifactId>
                               <version>${error-prone-support.version}</version>
                           </path>
                       </annotationProcessorPaths>
                       <compilerArgs>
                           <arg>
                               -Xplugin:ErrorProne
                               <!-- Add other Error Prone flags here. See
                               https://errorprone.info/docs/flags. -->
                           </arg>
                           <arg>-XDcompilePolicy=simple</arg>
                       </compilerArgs>
                       <!-- Enable this if you'd like to fail your build upon warnings. -->
                       <!-- <failOnWarning>true</failOnWarning> -->
                   </configuration>
               </plugin>
           </plugins>
       </pluginManagement>
    </build>

Gradle

  1. First, follow the installation guide of the gradle-errorprone-plugin.
  2. Next, edit your build.gradle file to add one or more Error Prone Support modules:

    dependencies {
       // Error Prone itself.
       errorprone("com.google.errorprone:error_prone_core:${errorProneVersion}")
       // Error Prone Support's additional bug checkers.
       errorprone("tech.picnic.error-prone-support:error-prone-contrib:${errorProneSupportVersion}")
       // Error Prone Support's Refaster rules.
       errorprone("tech.picnic.error-prone-support:refaster-runner:${errorProneSupportVersion}")
    }
    
    tasks.withType(JavaCompile).configureEach {
       options.errorprone.disableWarningsInGeneratedCode = true
       // Add other Error Prone flags here. See:
       // - https://github.com/tbroyer/gradle-errorprone-plugin#configuration
       // - https://errorprone.info/docs/flags
    }

Seeing it in action

Consider the following example code:

import com.google.common.collect.ImmutableSet;
import java.math.BigDecimal;

public class Example {
  static BigDecimal getNumber() {
    return BigDecimal.valueOf(0);
  }

  public ImmutableSet<Integer> getSet() {
    ImmutableSet<Integer> set = ImmutableSet.of(1);
    return ImmutableSet.copyOf(set);
  }
}

If the installation was successful, then building the above code with Maven should yield two compiler warnings:

$ mvn clean install
...
[INFO] Example.java:[9,34] [Refaster Rule] BigDecimalRules.BigDecimalZero: Refactoring opportunity
    (see https://error-prone.picnic.tech/refasterrules/BigDecimalRules#BigDecimalZero)
  Did you mean 'return BigDecimal.ZERO;'?
...
[WARNING] Example.java:[13,35] [IdentityConversion] This method invocation appears redundant; remove it or suppress this warning and add a comment explaining its purpose
    (see https://error-prone.picnic.tech/bugpatterns/IdentityConversion)
  Did you mean 'return set;' or '@SuppressWarnings("IdentityConversion") public ImmutableSet<Integer> getSet() {'?
...

Two things are kicking in here:

  1. An Error Prone BugChecker that flags unnecessary identity conversions.
  2. A Refaster rule capable of rewriting expressions of the form BigDecimal.valueOf(0) and new BigDecimal(0) to BigDecimal.ZERO.

Be sure to check out all bug checks and refaster rules.

👷 Developing Error Prone Support

This is a Maven project, so running mvn clean install performs a full clean build and installs the library to your local Maven repository.

Once you've made changes, the build may fail due to a warning or error emitted by static code analysis. The flags and commands listed below allow you to suppress or (in a large subset of cases) automatically fix such cases. Make sure to carefully check the available options, as this can save you significant amounts of development time!

Relevant Maven build parameters:

Other highly relevant commands:

When running the project's tests in IntelliJ IDEA, you might see the following error:

java: exporting a package from system module jdk.compiler is not allowed with --release

If this happens, go to Settings -> Build, Execution, Deployment -> Compiler -> Java Compiler and deselect the option Use '--release' option for cross-compilation (Java 9 and later). See IDEA-288052 for details.

💡 How it works

This project provides additional BugChecker implementations.

✍️ Contributing

Want to report or fix a bug, suggest or add a new feature, or improve the documentation? That's awesome! Please read our contribution guidelines.

Security

If you want to report a security vulnerability, please do so through a private channel; please see our security policy for details.