mirror of
https://github.com/google/guava.git
synced 2024-10-23 08:44:54 +08:00
Make our Android builds work with an Android bootclasspath.
Notably: - Remove all usages of `AnnotatedType` from the Android flavor. - Make `NullPointerTester` a no-op in the Android flavor (instead of only in the Android flavor _when running under an Android VM_). - (This requires removing its tests from the Android flavor entirely, rather than merely skipping them during our internal Android-VM test runs.) In both cases, these changes apply only to (a) guava-android and (b) our actual internal _Android_ builds. In contrast, in the internal copy of the backport _that we test under a JRE_, the `AnnotatedType` APIs are still in place, and `NullPointerTester` still runs. RELNOTES=`reflect`: In `guava-android` only, removed `Invokable.getAnnotatedReturnType()` and `Parameter.getAnnotatedType()`. These methods never worked in an Android VM, and to reflect that, they were born `@Deprecated`, `@Beta`, and `@DoNotCall`. They're now preventing us from rolling out some new Android compatibility testing. PiperOrigin-RevId: 583032835
This commit is contained in:
parent
7feac90308
commit
045cd8428f
@ -35,7 +35,6 @@ import com.google.common.reflect.Reflection;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Member;
|
||||
@ -43,7 +42,6 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
@ -353,9 +351,9 @@ public final class NullPointerTester {
|
||||
@Nullable Object instance, Invokable<?, ?> invokable, int paramIndex, Class<?> testedClass) {
|
||||
/*
|
||||
* com.google.common is starting to rely on type-use annotations, which aren't visible under
|
||||
* Android VMs. So we skip testing there.
|
||||
* Android VMs and in open-source guava-android. So we skip testing there.
|
||||
*/
|
||||
if (isAndroid() && Reflection.getPackageName(testedClass).startsWith("com.google.common")) {
|
||||
if (Reflection.getPackageName(testedClass).startsWith("com.google.common")) {
|
||||
return;
|
||||
}
|
||||
if (isPrimitiveOrNullable(invokable.getParameters().get(paramIndex))) {
|
||||
@ -612,39 +610,19 @@ public final class NullPointerTester {
|
||||
* don't know that anyone uses it there, anyway.
|
||||
*/
|
||||
private enum NullnessAnnotationReader {
|
||||
// Usages (which are unsafe only for Android) are guarded by the annotatedTypeExists() check.
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidApiChecker", "DoNotCall", "deprecation"})
|
||||
@SuppressWarnings("Java7ApiChecker")
|
||||
FROM_DECLARATION_AND_TYPE_USE_ANNOTATIONS {
|
||||
@Override
|
||||
@IgnoreJRERequirement
|
||||
boolean isNullable(Invokable<?, ?> invokable) {
|
||||
return FROM_DECLARATION_ANNOTATIONS_ONLY.isNullable(invokable)
|
||||
|| containsNullable(invokable.getAnnotatedReturnType().getAnnotations());
|
||||
;
|
||||
// TODO(cpovirk): Should we also check isNullableTypeVariable?
|
||||
}
|
||||
|
||||
@Override
|
||||
@IgnoreJRERequirement
|
||||
boolean isNullable(Parameter param) {
|
||||
return FROM_DECLARATION_ANNOTATIONS_ONLY.isNullable(param)
|
||||
|| containsNullable(param.getAnnotatedType().getAnnotations())
|
||||
|| isNullableTypeVariable(param.getAnnotatedType().getType());
|
||||
}
|
||||
|
||||
@IgnoreJRERequirement
|
||||
boolean isNullableTypeVariable(Type type) {
|
||||
if (!(type instanceof TypeVariable)) {
|
||||
return false;
|
||||
}
|
||||
TypeVariable<?> typeVar = (TypeVariable<?>) type;
|
||||
for (AnnotatedType bound : typeVar.getAnnotatedBounds()) {
|
||||
// Until Java 15, the isNullableTypeVariable case here won't help:
|
||||
// https://bugs.openjdk.java.net/browse/JDK-8202469
|
||||
if (containsNullable(bound.getAnnotations()) || isNullableTypeVariable(bound.getType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
;
|
||||
}
|
||||
},
|
||||
FROM_DECLARATION_ANNOTATIONS_ONLY {
|
||||
@ -663,9 +641,4 @@ public final class NullPointerTester {
|
||||
|
||||
abstract boolean isNullable(Parameter param);
|
||||
}
|
||||
|
||||
private static boolean isAndroid() {
|
||||
// Arguably it would make more sense to test "can we see type-use annotations" directly....
|
||||
return checkNotNull(System.getProperty("java.runtime.name", "")).contains("Android");
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -16,14 +16,11 @@ package com.google.common.reflect;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import com.google.errorprone.annotations.DoNotCall;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Member;
|
||||
@ -278,7 +275,7 @@ public abstract class Invokable<T, R> implements AnnotatedElement, Member {
|
||||
Type[] parameterTypes = getGenericParameterTypes();
|
||||
Annotation[][] annotations = getParameterAnnotations();
|
||||
@Nullable Object[] annotatedTypes =
|
||||
ANNOTATED_TYPE_EXISTS ? getAnnotatedParameterTypes() : new Object[parameterTypes.length];
|
||||
new Object[parameterTypes.length];
|
||||
ImmutableList.Builder<Parameter> builder = ImmutableList.builder();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
builder.add(
|
||||
@ -343,10 +340,6 @@ public abstract class Invokable<T, R> implements AnnotatedElement, Member {
|
||||
|
||||
abstract Type[] getGenericParameterTypes();
|
||||
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
|
||||
@IgnoreJRERequirement
|
||||
abstract AnnotatedType[] getAnnotatedParameterTypes();
|
||||
|
||||
/** This should never return a type that's not a subtype of Throwable. */
|
||||
abstract Type[] getGenericExceptionTypes();
|
||||
|
||||
@ -354,22 +347,6 @@ public abstract class Invokable<T, R> implements AnnotatedElement, Member {
|
||||
|
||||
abstract Type getGenericReturnType();
|
||||
|
||||
/**
|
||||
* Returns the {@link AnnotatedType} for the return type.
|
||||
*
|
||||
* <p>This method will fail if run under an Android VM.
|
||||
*
|
||||
* @since NEXT for guava-android (available since 14.0 in guava-jre)
|
||||
* @deprecated This method does not work under Android VMs. It is safe to use from guava-jre, but
|
||||
* this copy in guava-android is not safe to use.
|
||||
*/
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
|
||||
@DoNotCall("fails under Android VMs; do not use from guava-android")
|
||||
@Deprecated
|
||||
@IgnoreJRERequirement
|
||||
@Beta
|
||||
public abstract AnnotatedType getAnnotatedReturnType();
|
||||
|
||||
static class MethodInvokable<T> extends Invokable<T, Object> {
|
||||
|
||||
final Method method;
|
||||
@ -396,21 +373,6 @@ public abstract class Invokable<T, R> implements AnnotatedElement, Member {
|
||||
return method.getGenericParameterTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
|
||||
@IgnoreJRERequirement
|
||||
AnnotatedType[] getAnnotatedParameterTypes() {
|
||||
return method.getAnnotatedParameterTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker", "DoNotCall"})
|
||||
@DoNotCall
|
||||
@IgnoreJRERequirement
|
||||
public AnnotatedType getAnnotatedReturnType() {
|
||||
return method.getAnnotatedReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
Type[] getGenericExceptionTypes() {
|
||||
return method.getGenericExceptionTypes();
|
||||
@ -488,21 +450,6 @@ public abstract class Invokable<T, R> implements AnnotatedElement, Member {
|
||||
return types;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
|
||||
@IgnoreJRERequirement
|
||||
AnnotatedType[] getAnnotatedParameterTypes() {
|
||||
return constructor.getAnnotatedParameterTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker", "DoNotCall"})
|
||||
@DoNotCall
|
||||
@IgnoreJRERequirement
|
||||
public AnnotatedType getAnnotatedReturnType() {
|
||||
return constructor.getAnnotatedReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
Type[] getGenericExceptionTypes() {
|
||||
return constructor.getGenericExceptionTypes();
|
||||
|
@ -15,15 +15,11 @@
|
||||
package com.google.common.reflect;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.annotations.DoNotCall;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import javax.annotation.CheckForNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
@ -42,7 +38,7 @@ public final class Parameter implements AnnotatedElement {
|
||||
private final ImmutableList<Annotation> annotations;
|
||||
|
||||
/**
|
||||
* An {@link AnnotatedType} instance, or {@code null} under Android VMs (possible only when using
|
||||
* An {@code AnnotatedType} instance, or {@code null} under Android VMs (possible only when using
|
||||
* the Android flavor of Guava). The field is declared with a type of {@code Object} to avoid
|
||||
* compatibility problems on Android VMs. The corresponding accessor method, however, can have the
|
||||
* more specific return type as long as users are careful to guard calls to it with version checks
|
||||
@ -131,24 +127,6 @@ public final class Parameter implements AnnotatedElement {
|
||||
return cast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link AnnotatedType} of the parameter.
|
||||
*
|
||||
* <p>This method will fail if run under an Android VM.
|
||||
*
|
||||
* @since NEXT for guava-android (available since 25.1 in guava-jre)
|
||||
* @deprecated This method does not work under Android VMs. It is safe to use from guava-jre, but
|
||||
* this copy in guava-android is not safe to use.
|
||||
*/
|
||||
@Beta
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
|
||||
@Deprecated
|
||||
@DoNotCall("fails under Android VMs; do not use from guava-android")
|
||||
@IgnoreJRERequirement
|
||||
public AnnotatedType getAnnotatedType() {
|
||||
return requireNonNull((AnnotatedType) annotatedType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@CheckForNull Object obj) {
|
||||
if (obj instanceof Parameter) {
|
||||
|
@ -352,13 +352,6 @@ public final class NullPointerTester {
|
||||
*/
|
||||
private void testParameter(
|
||||
@Nullable Object instance, Invokable<?, ?> invokable, int paramIndex, Class<?> testedClass) {
|
||||
/*
|
||||
* com.google.common is starting to rely on type-use annotations, which aren't visible under
|
||||
* Android VMs. So we skip testing there.
|
||||
*/
|
||||
if (isAndroid() && Reflection.getPackageName(testedClass).startsWith("com.google.common")) {
|
||||
return;
|
||||
}
|
||||
if (isPrimitiveOrNullable(invokable.getParameters().get(paramIndex))) {
|
||||
return; // there's nothing to test
|
||||
}
|
||||
@ -613,11 +606,9 @@ public final class NullPointerTester {
|
||||
* don't know that anyone uses it there, anyway.
|
||||
*/
|
||||
private enum NullnessAnnotationReader {
|
||||
// Usages (which are unsafe only for Android) are guarded by the annotatedTypeExists() check.
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidApiChecker", "DoNotCall", "deprecation"})
|
||||
@SuppressWarnings("Java7ApiChecker")
|
||||
FROM_DECLARATION_AND_TYPE_USE_ANNOTATIONS {
|
||||
@Override
|
||||
@IgnoreJRERequirement
|
||||
boolean isNullable(Invokable<?, ?> invokable) {
|
||||
return FROM_DECLARATION_ANNOTATIONS_ONLY.isNullable(invokable)
|
||||
|| containsNullable(invokable.getAnnotatedReturnType().getAnnotations());
|
||||
@ -625,14 +616,12 @@ public final class NullPointerTester {
|
||||
}
|
||||
|
||||
@Override
|
||||
@IgnoreJRERequirement
|
||||
boolean isNullable(Parameter param) {
|
||||
return FROM_DECLARATION_ANNOTATIONS_ONLY.isNullable(param)
|
||||
|| containsNullable(param.getAnnotatedType().getAnnotations())
|
||||
|| isNullableTypeVariable(param.getAnnotatedType().getType());
|
||||
}
|
||||
|
||||
@IgnoreJRERequirement
|
||||
boolean isNullableTypeVariable(Type type) {
|
||||
if (!(type instanceof TypeVariable)) {
|
||||
return false;
|
||||
@ -664,9 +653,4 @@ public final class NullPointerTester {
|
||||
|
||||
abstract boolean isNullable(Parameter param);
|
||||
}
|
||||
|
||||
private static boolean isAndroid() {
|
||||
// Arguably it would make more sense to test "can we see type-use annotations" directly....
|
||||
return checkNotNull(System.getProperty("java.runtime.name", "")).contains("Android");
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
*
|
||||
* @author Ben Yu
|
||||
*/
|
||||
@AndroidIncompatible // NullPointerTester refuses to run for c.g.c under Android
|
||||
public class ClassSanityTesterTest extends TestCase {
|
||||
|
||||
private final ClassSanityTester tester = new ClassSanityTester();
|
||||
|
@ -57,7 +57,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
* @author Mick Killianey
|
||||
*/
|
||||
@SuppressWarnings("CheckReturnValue")
|
||||
@AndroidIncompatible // NullPointerTester refuses to run for c.g.c under Android
|
||||
public class NullPointerTesterTest extends TestCase {
|
||||
|
||||
/** Non-NPE RuntimeException. */
|
||||
|
@ -341,8 +341,7 @@ public abstract class Invokable<T, R> implements AnnotatedElement, Member {
|
||||
|
||||
abstract Type[] getGenericParameterTypes();
|
||||
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
|
||||
@IgnoreJRERequirement
|
||||
@SuppressWarnings("Java7ApiChecker")
|
||||
abstract AnnotatedType[] getAnnotatedParameterTypes();
|
||||
|
||||
/** This should never return a type that's not a subtype of Throwable. */
|
||||
@ -355,12 +354,9 @@ public abstract class Invokable<T, R> implements AnnotatedElement, Member {
|
||||
/**
|
||||
* Returns the {@link AnnotatedType} for the return type.
|
||||
*
|
||||
* <p>This method will fail if run under an Android VM.
|
||||
*
|
||||
* @since 14.0 for guava-jre (available since 32.0.0 in guava-android)
|
||||
* @since 14.0
|
||||
*/
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
|
||||
@IgnoreJRERequirement
|
||||
@SuppressWarnings("Java7ApiChecker")
|
||||
public abstract AnnotatedType getAnnotatedReturnType();
|
||||
|
||||
static class MethodInvokable<T> extends Invokable<T, Object> {
|
||||
@ -390,15 +386,13 @@ public abstract class Invokable<T, R> implements AnnotatedElement, Member {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
|
||||
@IgnoreJRERequirement
|
||||
@SuppressWarnings("Java7ApiChecker")
|
||||
AnnotatedType[] getAnnotatedParameterTypes() {
|
||||
return method.getAnnotatedParameterTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker", "DoNotCall"})
|
||||
@IgnoreJRERequirement
|
||||
@SuppressWarnings("Java7ApiChecker")
|
||||
public AnnotatedType getAnnotatedReturnType() {
|
||||
return method.getAnnotatedReturnType();
|
||||
}
|
||||
@ -481,15 +475,13 @@ public abstract class Invokable<T, R> implements AnnotatedElement, Member {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
|
||||
@IgnoreJRERequirement
|
||||
@SuppressWarnings("Java7ApiChecker")
|
||||
AnnotatedType[] getAnnotatedParameterTypes() {
|
||||
return constructor.getAnnotatedParameterTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker", "DoNotCall"})
|
||||
@IgnoreJRERequirement
|
||||
@SuppressWarnings("Java7ApiChecker")
|
||||
public AnnotatedType getAnnotatedReturnType() {
|
||||
return constructor.getAnnotatedReturnType();
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public final class Parameter implements AnnotatedElement {
|
||||
private final ImmutableList<Annotation> annotations;
|
||||
|
||||
/**
|
||||
* An {@link AnnotatedType} instance, or {@code null} under Android VMs (possible only when using
|
||||
* An {@code AnnotatedType} instance, or {@code null} under Android VMs (possible only when using
|
||||
* the Android flavor of Guava). The field is declared with a type of {@code Object} to avoid
|
||||
* compatibility problems on Android VMs. The corresponding accessor method, however, can have the
|
||||
* more specific return type as long as users are careful to guard calls to it with version checks
|
||||
@ -93,7 +93,9 @@ public final class Parameter implements AnnotatedElement {
|
||||
return getDeclaredAnnotations();
|
||||
}
|
||||
|
||||
/** @since 18.0 */
|
||||
/**
|
||||
* @since 18.0
|
||||
*/
|
||||
@Override
|
||||
public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
|
||||
return getDeclaredAnnotationsByType(annotationType);
|
||||
@ -105,7 +107,9 @@ public final class Parameter implements AnnotatedElement {
|
||||
return annotations.toArray(new Annotation[0]);
|
||||
}
|
||||
|
||||
/** @since 18.0 */
|
||||
/**
|
||||
* @since 18.0
|
||||
*/
|
||||
@Override
|
||||
@CheckForNull
|
||||
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationType) {
|
||||
@ -113,7 +117,9 @@ public final class Parameter implements AnnotatedElement {
|
||||
return FluentIterable.from(annotations).filter(annotationType).first().orNull();
|
||||
}
|
||||
|
||||
/** @since 18.0 */
|
||||
/**
|
||||
* @since 18.0
|
||||
*/
|
||||
@Override
|
||||
public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationType) {
|
||||
@Nullable
|
||||
@ -126,12 +132,9 @@ public final class Parameter implements AnnotatedElement {
|
||||
/**
|
||||
* Returns the {@link AnnotatedType} of the parameter.
|
||||
*
|
||||
* <p>This method will fail if run under an Android VM.
|
||||
*
|
||||
* @since 25.1 for guava-jre (available since 32.0.0 in guava-android)
|
||||
* @since 25.1 for guava-jre
|
||||
*/
|
||||
@SuppressWarnings({"Java7ApiChecker", "AndroidJdkLibsChecker"})
|
||||
@IgnoreJRERequirement
|
||||
@SuppressWarnings("Java7ApiChecker")
|
||||
public AnnotatedType getAnnotatedType() {
|
||||
return requireNonNull((AnnotatedType) annotatedType);
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
# Warning: common.reflect (like reflection in general) is typically slow and
|
||||
# unreliable under Android. We do not recommend using it. This Proguard config
|
||||
# exists only to avoid breaking the builds of users who already have
|
||||
# common.reflect in their transitive dependencies.
|
||||
#
|
||||
-dontwarn com.google.common.reflect.Invokable
|
||||
-dontwarn com.google.common.reflect.Invokable$ConstructorInvokable
|
||||
-dontwarn com.google.common.reflect.Invokable$MethodInvokable
|
||||
-dontwarn com.google.common.reflect.Parameter
|
Loading…
Reference in New Issue
Block a user