Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce/extend RequireNonNullElse{,Get} Refaster rules #425

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
import static java.util.Objects.requireNonNullElse;
import static java.util.Objects.requireNonNullElseGet;

import com.google.common.base.MoreObjects;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;

Expand Down Expand Up @@ -43,13 +47,18 @@ boolean after(@Nullable Object object) {
}
}

/** Prefer {@link Objects#requireNonNullElse(Object, Object)} over the Guava alternative. */
// XXX: This rule is not valid in case `second` is `@Nullable`: in that case the Guava variant
// will return `null`, while the JDK variant will throw an NPE.
/**
* Prefer {@link Objects#requireNonNullElse(Object, Object)} over non-JDK or more contrived
* alternatives.
*/
// XXX: This rule is not valid in case `second` is `@Nullable`: in that case the Guava and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Stephan202 we looked into a NullableMatcher related to this, maybe we should prioritize that one again sometime. Such master could be useful here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/master/matcher/ ;)

Indeed I started work on that here, but I recall hitting some issues. (The AbstractMatcherTestChecker changes are part of that, but IIRC there was more. Would have to check out the branch and run the tests to refresh my memory.)

// `Optional` variants will return `null`, where the `requireNonNullElse` alternative will throw
// an NPE.
static final class RequireNonNullElse<T> {
@BeforeTemplate
T before(T first, T second) {
return MoreObjects.firstNonNull(first, second);
return Refaster.anyOf(
MoreObjects.firstNonNull(first, second), Optional.ofNullable(first).orElse(second));
}

@AfterTemplate
Expand All @@ -59,6 +68,26 @@ T after(T first, T second) {
}
}

/**
* Prefer {@link Objects#requireNonNullElseGet(Object, Supplier)} over more contrived
* alternatives.
*/
// XXX: This rule is not valid in case `supplier` yields `@Nullable` values: in that case the
// `Optional` variant will return `null`, where the `requireNonNullElseGet` alternative will throw
// an NPE.
static final class RequireNonNullElseGet<T, S extends T> {
@BeforeTemplate
T before(T object, Supplier<S> supplier) {
return Optional.ofNullable(object).orElseGet(supplier);
}

@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
T after(T object, Supplier<S> supplier) {
return requireNonNullElseGet(object, supplier);
}
}

/** Prefer {@link Objects#isNull(Object)} over the equivalent lambda function. */
static final class IsNullFunction<T> {
@BeforeTemplate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableSet;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;

final class NullRulesTest implements RefasterRuleCollectionTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(MoreObjects.class);
return ImmutableSet.of(MoreObjects.class, Optional.class);
}

boolean testIsNull() {
Expand All @@ -20,8 +21,13 @@ boolean testIsNotNull() {
return Objects.nonNull("foo");
}

String testRequireNonNullElse() {
return MoreObjects.firstNonNull("foo", "bar");
ImmutableSet<String> testRequireNonNullElse() {
return ImmutableSet.of(
MoreObjects.firstNonNull("foo", "bar"), Optional.ofNullable("baz").orElse("qux"));
}

String testRequireNonNullElseGet() {
return Optional.ofNullable("foo").orElseGet(() -> "bar");
}

long testIsNullFunction() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package tech.picnic.errorprone.refasterrules;

import static java.util.Objects.requireNonNullElse;
import static java.util.Objects.requireNonNullElseGet;

import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableSet;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;

final class NullRulesTest implements RefasterRuleCollectionTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(MoreObjects.class);
return ImmutableSet.of(MoreObjects.class, Optional.class);
}

boolean testIsNull() {
Expand All @@ -22,8 +24,12 @@ boolean testIsNotNull() {
return "foo" != null;
}

String testRequireNonNullElse() {
return requireNonNullElse("foo", "bar");
ImmutableSet<String> testRequireNonNullElse() {
return ImmutableSet.of(requireNonNullElse("foo", "bar"), requireNonNullElse("baz", "qux"));
}

String testRequireNonNullElseGet() {
return requireNonNullElseGet("foo", () -> "bar");
}

long testIsNullFunction() {
Expand Down