Introduce Class{Literal,Reference}Cast Refaster rules (#1269)

This commit is contained in:
Mohamed Sameh
2024-08-11 15:01:53 +02:00
committed by GitHub
parent 366cdda3d8
commit 3d9aab7c5b
3 changed files with 73 additions and 12 deletions

View File

@@ -3,6 +3,7 @@ package tech.picnic.errorprone.refasterrules;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import java.util.function.Function;
import java.util.function.Predicate;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
@@ -37,7 +38,12 @@ final class ClassRules {
}
}
/** Prefer {@link Class#isInstance(Object)} method references over more verbose alternatives. */
/**
* Prefer {@link Class#isInstance(Object)} method references over lambda expressions that require
* naming a variable.
*/
// XXX: Once the `ClassReferenceIsInstancePredicate` rule is dropped, rename this rule to just
// `ClassIsInstancePredicate`.
static final class ClassLiteralIsInstancePredicate<T, S> {
@BeforeTemplate
Predicate<S> before() {
@@ -50,7 +56,11 @@ final class ClassRules {
}
}
/** Prefer {@link Class#isInstance(Object)} method references over more verbose alternatives. */
/**
* Prefer {@link Class#isInstance(Object)} method references over lambda expressions that require
* naming a variable.
*/
// XXX: Drop this rule once the `MethodReferenceUsage` rule is enabled by default.
static final class ClassReferenceIsInstancePredicate<T, S> {
@BeforeTemplate
Predicate<S> before(Class<T> clazz) {
@@ -62,4 +72,39 @@ final class ClassRules {
return clazz::isInstance;
}
}
/**
* Prefer {@link Class#cast(Object)} method references over lambda expressions that require naming
* a variable.
*/
// XXX: Once the `ClassReferenceCast` rule is dropped, rename this rule to just `ClassCast`.
static final class ClassLiteralCast<T, S> {
@BeforeTemplate
@SuppressWarnings("unchecked")
Function<T, S> before() {
return t -> (S) t;
}
@AfterTemplate
Function<T, S> after() {
return Refaster.<S>clazz()::cast;
}
}
/**
* Prefer {@link Class#cast(Object)} method references over lambda expressions that require naming
* a variable.
*/
// XXX: Drop this rule once the `MethodReferenceUsage` rule is enabled by default.
static final class ClassReferenceCast<T, S> {
@BeforeTemplate
Function<T, S> before(Class<? extends S> clazz) {
return o -> clazz.cast(o);
}
@AfterTemplate
Function<T, S> after(Class<? extends S> clazz) {
return clazz::cast;
}
}
}

View File

@@ -1,26 +1,34 @@
package tech.picnic.errorprone.refasterrules;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.util.function.Function;
import java.util.function.Predicate;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class ClassRulesTest implements RefasterRuleCollectionTestCase {
boolean testClassIsInstance() throws IOException {
boolean testClassIsInstance() {
return CharSequence.class.isAssignableFrom("foo".getClass());
}
ImmutableSet<Boolean> testInstanceof() throws IOException {
ImmutableSet<Boolean> testInstanceof() {
Class<?> clazz = CharSequence.class;
return ImmutableSet.of(CharSequence.class.isInstance("foo"), clazz.isInstance("bar"));
}
Predicate<String> testClassLiteralIsInstancePredicate() throws IOException {
Predicate<String> testClassLiteralIsInstancePredicate() {
return s -> s instanceof CharSequence;
}
Predicate<String> testClassReferenceIsInstancePredicate() throws IOException {
Predicate<String> testClassReferenceIsInstancePredicate() {
Class<?> clazz = CharSequence.class;
return s -> clazz.isInstance(s);
}
Function<Number, Integer> testClassLiteralCast() {
return i -> (Integer) i;
}
Function<Number, Integer> testClassReferenceCast() {
return i -> Integer.class.cast(i);
}
}

View File

@@ -1,26 +1,34 @@
package tech.picnic.errorprone.refasterrules;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.util.function.Function;
import java.util.function.Predicate;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class ClassRulesTest implements RefasterRuleCollectionTestCase {
boolean testClassIsInstance() throws IOException {
boolean testClassIsInstance() {
return CharSequence.class.isInstance("foo");
}
ImmutableSet<Boolean> testInstanceof() throws IOException {
ImmutableSet<Boolean> testInstanceof() {
Class<?> clazz = CharSequence.class;
return ImmutableSet.of("foo" instanceof CharSequence, clazz.isInstance("bar"));
}
Predicate<String> testClassLiteralIsInstancePredicate() throws IOException {
Predicate<String> testClassLiteralIsInstancePredicate() {
return CharSequence.class::isInstance;
}
Predicate<String> testClassReferenceIsInstancePredicate() throws IOException {
Predicate<String> testClassReferenceIsInstancePredicate() {
Class<?> clazz = CharSequence.class;
return clazz::isInstance;
}
Function<Number, Integer> testClassLiteralCast() {
return Integer.class::cast;
}
Function<Number, Integer> testClassReferenceCast() {
return Integer.class::cast;
}
}