Skip to content

Commit

Permalink
Introduce Guava Preconditions Refaster rules (#292)
Browse files Browse the repository at this point in the history
  • Loading branch information
werli authored and rickie committed Oct 20, 2022
1 parent fa6a817 commit 8e5314c
Show file tree
Hide file tree
Showing 7 changed files with 317 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,33 @@ int before(int index, int size) {
}

@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
int after(int index, int size) {
return checkIndex(index, size);
}
}

/**
* Prefer {@link Objects#checkIndex(int, int)} over less descriptive or more verbose alternatives.
*
* <p>If a custom error message is desired, consider using Guava's {@link
* com.google.common.base.Preconditions#checkElementIndex(int, int, String)}.
*/
static final class CheckIndexConditional {
@BeforeTemplate
void before(int index, int size) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
}
}

@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
void after(int index, int size) {
checkIndex(index, size);
}
}

// XXX: We could add a rule for `new EnumMap(Map<K, ? extends V> m)`, but that constructor does
// not allow an empty non-EnumMap to be provided.
static final class CreateEnumMap<K extends Enum<K>, V> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package tech.picnic.errorprone.refasterrules;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndex;
import static com.google.common.base.Preconditions.checkState;
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;

import com.google.common.base.Preconditions;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;

/** Refaster templates related to statements dealing with {@link Preconditions}. */
@OnlineDocumentation
final class PreconditionsRules {
private PreconditionsRules() {}

/** Prefer {@link Preconditions#checkArgument(boolean)} over more verbose alternatives. */
static final class CheckArgument {
@BeforeTemplate
void before(boolean condition) {
if (condition) {
throw new IllegalArgumentException();
}
}

@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
void after(boolean condition) {
checkArgument(!condition);
}
}

/** Prefer {@link Preconditions#checkArgument(boolean, Object)} over more verbose alternatives. */
static final class CheckArgumentWithMessage {
@BeforeTemplate
void before(boolean condition, String message) {
if (condition) {
throw new IllegalArgumentException(message);
}
}

@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
void after(boolean condition, String message) {
checkArgument(!condition, message);
}
}

/**
* Prefer {@link Preconditions#checkElementIndex(int, int, String)} over less descriptive or more
* verbose alternatives.
*
* <p>Note that the two-argument {@link Preconditions#checkElementIndex(int, int)} is better
* replaced with {@link java.util.Objects#checkIndex(int, int)}.
*/
static final class CheckElementIndexWithMessage {
@BeforeTemplate
void before(int index, int size, String message) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException(message);
}
}

@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
void after(int index, int size, String message) {
checkElementIndex(index, size, message);
}
}

/** Prefer {@link Preconditions#checkNotNull(Object)} over more verbose alternatives. */
static final class CheckNotNull<T> {
@BeforeTemplate
void before(T object) {
if (object == null) {
throw new NullPointerException();
}
}

@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
void after(T object) {
checkNotNull(object);
}
}

/** Prefer {@link Preconditions#checkNotNull(Object, Object)} over more verbose alternatives. */
static final class CheckNotNullWithMessage<T> {
@BeforeTemplate
void before(T object, String message) {
if (object == null) {
throw new NullPointerException(message);
}
}

@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
void after(T object, String message) {
checkNotNull(object, message);
}
}

/**
* Prefer {@link Preconditions#checkPositionIndex(int, int)} over less descriptive or more verbose
* alternatives.
*/
static final class CheckPositionIndex {
@BeforeTemplate
void before(int index, int size) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException();
}
}

@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
void after(int index, int size) {
checkPositionIndex(index, size);
}
}

/**
* Prefer {@link Preconditions#checkPositionIndex(int, int, String)} over less descriptive or more
* verbose alternatives.
*/
static final class CheckPositionIndexWithMessage {
@BeforeTemplate
void before(int index, int size, String message) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException(message);
}
}

@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
void after(int index, int size, String message) {
checkPositionIndex(index, size, message);
}
}

/** Prefer {@link Preconditions#checkState(boolean)} over more verbose alternatives. */
static final class CheckState {
@BeforeTemplate
void before(boolean condition) {
if (condition) {
throw new IllegalStateException();
}
}

@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
void after(boolean condition) {
checkState(!condition);
}
}

/** Prefer {@link Preconditions#checkState(boolean, Object)} over more verbose alternatives. */
static final class CheckStateWithMessage {
@BeforeTemplate
void before(boolean condition, String message) {
if (condition) {
throw new IllegalStateException(message);
}
}

@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
void after(boolean condition, String message) {
checkState(!condition, message);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ final class RefasterRulesTest {
MultimapRules.class,
NullRules.class,
OptionalRules.class,
PreconditionsRules.class,
PrimitiveRules.class,
ReactorRules.class,
RxJava2AdapterRules.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ int testCheckIndex() {
return Preconditions.checkElementIndex(0, 1);
}

void testCheckIndexConditional() {
if (1 < 0 || 1 >= 2) {
throw new IndexOutOfBoundsException();
}
}

Map<RoundingMode, String> testCreateEnumMap() {
return new HashMap<>();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Sets.toImmutableEnumSet;
import static java.util.Objects.checkIndex;

import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
Expand All @@ -19,7 +20,6 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;

Expand All @@ -38,7 +38,11 @@ public ImmutableSet<?> elidedTypesAndStaticImports() {
}

int testCheckIndex() {
return Objects.checkIndex(0, 1);
return checkIndex(0, 1);
}

void testCheckIndexConditional() {
checkIndex(1, 2);
}

Map<RoundingMode, String> testCreateEnumMap() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package tech.picnic.errorprone.refasterrules;

import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;

final class PreconditionsRulesTest implements RefasterRuleCollectionTestCase {
void testCheckArgument() {
if ("foo".isEmpty()) {
throw new IllegalArgumentException();
}
}

void testCheckArgumentWithMessage() {
if ("foo".isEmpty()) {
throw new IllegalArgumentException("The string is empty");
}
}

void testCheckElementIndexWithMessage() {
if (1 < 0 || 1 >= 2) {
throw new IndexOutOfBoundsException("My index");
}
}

void testCheckNotNull() {
if ("foo" == null) {
throw new NullPointerException();
}
}

void testCheckNotNullWithMessage() {
if ("foo" == null) {
throw new NullPointerException("The string is null");
}
}

void testCheckPositionIndex() {
if (1 < 0 || 1 > 2) {
throw new IndexOutOfBoundsException();
}
}

void testCheckPositionIndexWithMessage() {
if (1 < 0 || 1 > 2) {
throw new IndexOutOfBoundsException("My position");
}
}

void testCheckState() {
if ("foo".isEmpty()) {
throw new IllegalStateException();
}
}

void testCheckStateWithMessage() {
if ("foo".isEmpty()) {
throw new IllegalStateException("The string is empty");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package tech.picnic.errorprone.refasterrules;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndex;
import static com.google.common.base.Preconditions.checkState;

import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;

final class PreconditionsRulesTest implements RefasterRuleCollectionTestCase {
void testCheckArgument() {
checkArgument(!"foo".isEmpty());
}

void testCheckArgumentWithMessage() {
checkArgument(!"foo".isEmpty(), "The string is empty");
}

void testCheckElementIndexWithMessage() {
checkElementIndex(1, 2, "My index");
}

void testCheckNotNull() {
checkNotNull("foo");
}

void testCheckNotNullWithMessage() {
checkNotNull("foo", "The string is null");
}

void testCheckPositionIndex() {
checkPositionIndex(1, 2);
}

void testCheckPositionIndexWithMessage() {
checkPositionIndex(1, 2, "My position");
}

void testCheckState() {
checkState(!"foo".isEmpty());
}

void testCheckStateWithMessage() {
checkState(!"foo".isEmpty(), "The string is empty");
}
}

0 comments on commit 8e5314c

Please sign in to comment.