diff options
Diffstat (limited to 'guava/src/com/google/common')
124 files changed, 2028 insertions, 1251 deletions
diff --git a/guava/src/com/google/common/base/CharMatcher.java b/guava/src/com/google/common/base/CharMatcher.java index 4ed1e9a90..42dfca3d8 100644 --- a/guava/src/com/google/common/base/CharMatcher.java +++ b/guava/src/com/google/common/base/CharMatcher.java @@ -971,7 +971,7 @@ public abstract class CharMatcher implements Predicate<Character> { } /** Negation of a {@link FastMatcher}. */ - static class NegatedFastMatcher extends Negated { + private static class NegatedFastMatcher extends Negated { NegatedFastMatcher(CharMatcher original) { super(original); @@ -1015,7 +1015,7 @@ public abstract class CharMatcher implements Predicate<Character> { /** Implementation of {@link #any()}. */ private static final class Any extends NamedFastMatcher { - static final Any INSTANCE = new Any(); + static final CharMatcher INSTANCE = new Any(); private Any() { super("CharMatcher.any()"); @@ -1112,7 +1112,7 @@ public abstract class CharMatcher implements Predicate<Character> { /** Implementation of {@link #none()}. */ private static final class None extends NamedFastMatcher { - static final None INSTANCE = new None(); + static final CharMatcher INSTANCE = new None(); private None() { super("CharMatcher.none()"); @@ -1228,7 +1228,7 @@ public abstract class CharMatcher implements Predicate<Character> { static final int MULTIPLIER = 1682554634; static final int SHIFT = Integer.numberOfLeadingZeros(TABLE.length() - 1); - static final Whitespace INSTANCE = new Whitespace(); + static final CharMatcher INSTANCE = new Whitespace(); Whitespace() { super("CharMatcher.whitespace()"); @@ -1286,7 +1286,7 @@ public abstract class CharMatcher implements Predicate<Character> { /** Implementation of {@link #ascii()}. */ private static final class Ascii extends NamedFastMatcher { - static final Ascii INSTANCE = new Ascii(); + static final CharMatcher INSTANCE = new Ascii(); Ascii() { super("CharMatcher.ascii()"); @@ -1360,7 +1360,7 @@ public abstract class CharMatcher implements Predicate<Character> { return nines; } - static final Digit INSTANCE = new Digit(); + static final CharMatcher INSTANCE = new Digit(); private Digit() { super("CharMatcher.digit()", zeroes(), nines()); @@ -1370,7 +1370,7 @@ public abstract class CharMatcher implements Predicate<Character> { /** Implementation of {@link #javaDigit()}. */ private static final class JavaDigit extends CharMatcher { - static final JavaDigit INSTANCE = new JavaDigit(); + static final CharMatcher INSTANCE = new JavaDigit(); @Override public boolean matches(char c) { @@ -1386,7 +1386,7 @@ public abstract class CharMatcher implements Predicate<Character> { /** Implementation of {@link #javaLetter()}. */ private static final class JavaLetter extends CharMatcher { - static final JavaLetter INSTANCE = new JavaLetter(); + static final CharMatcher INSTANCE = new JavaLetter(); @Override public boolean matches(char c) { @@ -1402,7 +1402,7 @@ public abstract class CharMatcher implements Predicate<Character> { /** Implementation of {@link #javaLetterOrDigit()}. */ private static final class JavaLetterOrDigit extends CharMatcher { - static final JavaLetterOrDigit INSTANCE = new JavaLetterOrDigit(); + static final CharMatcher INSTANCE = new JavaLetterOrDigit(); @Override public boolean matches(char c) { @@ -1418,7 +1418,7 @@ public abstract class CharMatcher implements Predicate<Character> { /** Implementation of {@link #javaUpperCase()}. */ private static final class JavaUpperCase extends CharMatcher { - static final JavaUpperCase INSTANCE = new JavaUpperCase(); + static final CharMatcher INSTANCE = new JavaUpperCase(); @Override public boolean matches(char c) { @@ -1434,7 +1434,7 @@ public abstract class CharMatcher implements Predicate<Character> { /** Implementation of {@link #javaLowerCase()}. */ private static final class JavaLowerCase extends CharMatcher { - static final JavaLowerCase INSTANCE = new JavaLowerCase(); + static final CharMatcher INSTANCE = new JavaLowerCase(); @Override public boolean matches(char c) { @@ -1450,7 +1450,7 @@ public abstract class CharMatcher implements Predicate<Character> { /** Implementation of {@link #javaIsoControl()}. */ private static final class JavaIsoControl extends NamedFastMatcher { - static final JavaIsoControl INSTANCE = new JavaIsoControl(); + static final CharMatcher INSTANCE = new JavaIsoControl(); private JavaIsoControl() { super("CharMatcher.javaIsoControl()"); @@ -1475,7 +1475,7 @@ public abstract class CharMatcher implements Predicate<Character> { "\u0020\u00a0\u00ad\u0605\u061c\u06dd\u070f\u0891\u08e2\u1680\u180e\u200f\u202f\u2064\u206f" + "\u3000\uf8ff\ufeff\ufffb"; - static final Invisible INSTANCE = new Invisible(); + static final CharMatcher INSTANCE = new Invisible(); private Invisible() { super("CharMatcher.invisible()", RANGE_STARTS.toCharArray(), RANGE_ENDS.toCharArray()); @@ -1485,7 +1485,7 @@ public abstract class CharMatcher implements Predicate<Character> { /** Implementation of {@link #singleWidth()}. */ private static final class SingleWidth extends RangesMatcher { - static final SingleWidth INSTANCE = new SingleWidth(); + static final CharMatcher INSTANCE = new SingleWidth(); private SingleWidth() { super( diff --git a/guava/src/com/google/common/base/Converter.java b/guava/src/com/google/common/base/Converter.java index 63f4394f4..a34c734ab 100644 --- a/guava/src/com/google/common/base/Converter.java +++ b/guava/src/com/google/common/base/Converter.java @@ -571,7 +571,7 @@ public abstract class Converter<A, B> implements Function<A, B> { * "pass-through type". */ private static final class IdentityConverter<T> extends Converter<T, T> implements Serializable { - static final IdentityConverter<?> INSTANCE = new IdentityConverter<>(); + static final Converter<?, ?> INSTANCE = new IdentityConverter<>(); @Override protected T doForward(T t) { diff --git a/guava/src/com/google/common/base/Joiner.java b/guava/src/com/google/common/base/Joiner.java index fe1b40a5e..acb7d8d12 100644 --- a/guava/src/com/google/common/base/Joiner.java +++ b/guava/src/com/google/common/base/Joiner.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.util.AbstractList; import java.util.Arrays; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.annotation.CheckForNull; @@ -129,7 +130,9 @@ public class Joiner { @CanIgnoreReturnValue public final <A extends Appendable> A appendTo(A appendable, @Nullable Object[] parts) throws IOException { - return appendTo(appendable, Arrays.asList(parts)); + @SuppressWarnings("nullness") // TODO: b/316358623 - Remove suppression after fixing checker + List<?> partsList = Arrays.<@Nullable Object>asList(parts); + return appendTo(appendable, partsList); } /** Appends to {@code appendable} the string representation of each of the remaining arguments. */ @@ -179,7 +182,9 @@ public class Joiner { */ @CanIgnoreReturnValue public final StringBuilder appendTo(StringBuilder builder, @Nullable Object[] parts) { - return appendTo(builder, Arrays.asList(parts)); + @SuppressWarnings("nullness") // TODO: b/316358623 - Remove suppression after fixing checker + List<?> partsList = Arrays.<@Nullable Object>asList(parts); + return appendTo(builder, partsList); } /** @@ -219,7 +224,9 @@ public class Joiner { * previously configured separator between each. */ public final String join(@Nullable Object[] parts) { - return join(Arrays.asList(parts)); + @SuppressWarnings("nullness") // TODO: b/316358623 - Remove suppression after fixing checker + List<?> partsList = Arrays.<@Nullable Object>asList(parts); + return join(partsList); } /** diff --git a/guava/src/com/google/common/base/MoreObjects.java b/guava/src/com/google/common/base/MoreObjects.java index f3826d96f..1074336f5 100644 --- a/guava/src/com/google/common/base/MoreObjects.java +++ b/guava/src/com/google/common/base/MoreObjects.java @@ -439,7 +439,7 @@ public final class MoreObjects { } // Holder object for values that might be null and/or empty. - private static class ValueHolder { + static class ValueHolder { @CheckForNull String name; @CheckForNull Object value; @CheckForNull ValueHolder next; diff --git a/guava/src/com/google/common/base/PatternCompiler.java b/guava/src/com/google/common/base/PatternCompiler.java index 6a7b620b2..32505217f 100644 --- a/guava/src/com/google/common/base/PatternCompiler.java +++ b/guava/src/com/google/common/base/PatternCompiler.java @@ -16,6 +16,7 @@ package com.google.common.base; import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; +import com.google.errorprone.annotations.RestrictedApi; /** * Pluggable interface for compiling a regex pattern. By default this package uses the {@code @@ -31,11 +32,17 @@ interface PatternCompiler { * * @throws IllegalArgumentException if the pattern is invalid */ + @RestrictedApi( + explanation = "PatternCompiler is an implementation detail of com.google.common.base", + allowedOnPath = ".*/com/google/common/base/.*") CommonPattern compile(String pattern); /** * Returns {@code true} if the regex implementation behaves like Perl -- notably, by supporting * possessive quantifiers but also being susceptible to catastrophic backtracking. */ + @RestrictedApi( + explanation = "PatternCompiler is an implementation detail of com.google.common.base", + allowedOnPath = ".*/com/google/common/base/.*") boolean isPcreLike(); } diff --git a/guava/src/com/google/common/base/Splitter.java b/guava/src/com/google/common/base/Splitter.java index f8415a79a..de8f24441 100644 --- a/guava/src/com/google/common/base/Splitter.java +++ b/guava/src/com/google/common/base/Splitter.java @@ -217,10 +217,11 @@ public final class Splitter { @J2ktIncompatible @GwtIncompatible // java.util.regex public static Splitter on(Pattern separatorPattern) { - return on(new JdkPattern(separatorPattern)); + return onPatternInternal(new JdkPattern(separatorPattern)); } - private static Splitter on(final CommonPattern separatorPattern) { + /** Internal utility; see {@link #on(Pattern)} instead. */ + static Splitter onPatternInternal(final CommonPattern separatorPattern) { checkArgument( !separatorPattern.matcher("").matches(), "The pattern may not match the empty string: %s", @@ -261,7 +262,7 @@ public final class Splitter { @J2ktIncompatible @GwtIncompatible // java.util.regex public static Splitter onPattern(String separatorPattern) { - return on(Platform.compilePattern(separatorPattern)); + return onPatternInternal(Platform.compilePattern(separatorPattern)); } /** diff --git a/guava/src/com/google/common/base/Throwables.java b/guava/src/com/google/common/base/Throwables.java index 23936897d..e37a3d99d 100644 --- a/guava/src/com/google/common/base/Throwables.java +++ b/guava/src/com/google/common/base/Throwables.java @@ -140,18 +140,7 @@ public final class Throwables { /** * Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@link - * RuntimeException} or {@link Error}. Example usage: - * - * <pre> - * try { - * someMethodThatCouldThrowAnything(); - * } catch (IKnowWhatToDoWithThisException e) { - * handle(e); - * } catch (Throwable t) { - * Throwables.propagateIfPossible(t); - * throw new RuntimeException("unexpected", t); - * } - * </pre> + * RuntimeException} or {@link Error}. * * @deprecated Use {@link #throwIfUnchecked}, which has the same behavior but rejects {@code * null}. @@ -167,18 +156,10 @@ public final class Throwables { /** * Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@link - * RuntimeException}, {@link Error}, or {@code declaredType}. Example usage: + * RuntimeException}, {@link Error}, or {@code declaredType}. * - * <pre> - * try { - * someMethodThatCouldThrowAnything(); - * } catch (IKnowWhatToDoWithThisException e) { - * handle(e); - * } catch (Throwable t) { - * Throwables.propagateIfPossible(t, OtherException.class); - * throw new RuntimeException("unexpected", t); - * } - * </pre> + * <p><b>Discouraged</b> in favor of calling {@link #throwIfInstanceOf} and {@link + * #throwIfUnchecked}. * * @param throwable the Throwable to possibly propagate * @param declaredType the single checked exception type declared by the calling method @@ -193,10 +174,10 @@ public final class Throwables { /** * Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@link - * RuntimeException}, {@link Error}, {@code declaredType1}, or {@code declaredType2}. In the - * unlikely case that you have three or more declared checked exception types, you can handle them - * all by invoking these methods repeatedly. See usage example in {@link - * #propagateIfPossible(Throwable, Class)}. + * RuntimeException}, {@link Error}, {@code declaredType1}, or {@code declaredType2}. + * + * <p><b>Discouraged</b> in favor of calling {@link #throwIfInstanceOf} and {@link + * #throwIfUnchecked}. * * @param throwable the Throwable to possibly propagate * @param declaredType1 any checked exception type declared by the calling method @@ -235,10 +216,11 @@ public final class Throwables { * @param throwable the Throwable to propagate * @return nothing will ever be returned; this return type is only for your convenience, as * illustrated in the example above - * @deprecated Use {@code throw e} or {@code throw new RuntimeException(e)} directly, or use a - * combination of {@link #throwIfUnchecked} and {@code throw new RuntimeException(e)}. For - * background on the deprecation, read <a href="https://goo.gl/Ivn2kc">Why we deprecated - * {@code Throwables.propagate}</a>. + * @deprecated To preserve behavior, use {@code throw e} or {@code throw new RuntimeException(e)} + * directly, or use a combination of {@link #throwIfUnchecked} and {@code throw new + * RuntimeException(e)}. But consider whether users would be better off if your API threw a + * different type of exception. For background on the deprecation, read <a + * href="https://goo.gl/Ivn2kc">Why we deprecated {@code Throwables.propagate}</a>. */ @CanIgnoreReturnValue @J2ktIncompatible diff --git a/guava/src/com/google/common/base/internal/Finalizer.java b/guava/src/com/google/common/base/internal/Finalizer.java index b45ec1578..e8ddf320c 100644 --- a/guava/src/com/google/common/base/internal/Finalizer.java +++ b/guava/src/com/google/common/base/internal/Finalizer.java @@ -153,41 +153,62 @@ public class Finalizer implements Runnable { } /** - * Cleans up a single reference. Catches and logs all throwables. + * Cleans up the given reference and any other references already in the queue. Catches and logs + * all throwables. * - * @return true if the caller should continue, false if the associated FinalizableReferenceQueue - * is no longer referenced. + * @return true if the caller should continue to wait for more references to be added to the + * queue, false if the associated FinalizableReferenceQueue is no longer referenced. */ - private boolean cleanUp(Reference<?> reference) { + private boolean cleanUp(Reference<?> firstReference) { Method finalizeReferentMethod = getFinalizeReferentMethod(); if (finalizeReferentMethod == null) { return false; } - do { - /* - * This is for the benefit of phantom references. Weak and soft references will have already - * been cleared by this point. - */ - reference.clear(); - if (reference == frqReference) { - /* - * The client no longer has a reference to the FinalizableReferenceQueue. We can stop. - */ + if (!finalizeReference(firstReference, finalizeReferentMethod)) { + return false; + } + + /* + * Loop as long as we have references available so as not to waste CPU looking up the Method + * over and over again. + */ + while (true) { + Reference<?> furtherReference = queue.poll(); + if (furtherReference == null) { + return true; + } + if (!finalizeReference(furtherReference, finalizeReferentMethod)) { return false; } + } + } - try { - finalizeReferentMethod.invoke(reference); - } catch (Throwable t) { - logger.log(Level.SEVERE, "Error cleaning up after reference.", t); - } + /** + * Cleans up the given reference. Catches and logs all throwables. + * + * @return true if the caller should continue to clean up references from the queue, false if the + * associated FinalizableReferenceQueue is no longer referenced. + */ + private boolean finalizeReference(Reference<?> reference, Method finalizeReferentMethod) { + /* + * This is for the benefit of phantom references. Weak and soft references will have already + * been cleared by this point. + */ + reference.clear(); + if (reference == frqReference) { /* - * Loop as long as we have references available so as not to waste CPU looking up the Method - * over and over again. + * The client no longer has a reference to the FinalizableReferenceQueue. We can stop. */ - } while ((reference = queue.poll()) != null); + return false; + } + + try { + finalizeReferentMethod.invoke(reference); + } catch (Throwable t) { + logger.log(Level.SEVERE, "Error cleaning up after reference.", t); + } return true; } diff --git a/guava/src/com/google/common/cache/CacheBuilder.java b/guava/src/com/google/common/cache/CacheBuilder.java index bbb2b185b..6a964a290 100644 --- a/guava/src/com/google/common/cache/CacheBuilder.java +++ b/guava/src/com/google/common/cache/CacheBuilder.java @@ -569,8 +569,8 @@ public final class CacheBuilder<K, V> { * * @param weigher the weigher to use in calculating the weight of cache entries * @return this {@code CacheBuilder} instance (for chaining) - * @throws IllegalArgumentException if {@code size} is negative - * @throws IllegalStateException if a maximum size was already set + * @throws IllegalStateException if a weigher was already set or {@link #maximumSize} was + * previously called * @since 11.0 */ @GwtIncompatible // To be supported diff --git a/guava/src/com/google/common/cache/LocalCache.java b/guava/src/com/google/common/cache/LocalCache.java index 00fb43575..dd3590357 100644 --- a/guava/src/com/google/common/cache/LocalCache.java +++ b/guava/src/com/google/common/cache/LocalCache.java @@ -281,7 +281,8 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> // will result in random eviction behavior. int segmentShift = 0; int segmentCount = 1; - while (segmentCount < concurrencyLevel && (!evictsBySize() || segmentCount * 20 <= maxWeight)) { + while (segmentCount < concurrencyLevel + && (!evictsBySize() || segmentCount * 20L <= maxWeight)) { ++segmentShift; segmentCount <<= 1; } @@ -2183,12 +2184,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> if (createNewEntry) { try { - // Synchronizes on the entry to allow failing fast when a recursive load is - // detected. This may be circumvented when an entry is copied, but will fail fast most - // of the time. - synchronized (e) { - return loadSync(key, hash, loadingValueReference, loader); - } + return loadSync(key, hash, loadingValueReference, loader); } finally { statsCounter.recordMisses(1); } @@ -2204,7 +2200,22 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> throw new AssertionError(); } - checkState(!Thread.holdsLock(e), "Recursive load of: %s", key); + // As of this writing, the only prod ValueReference implementation for which isLoading() is + // true is LoadingValueReference. (Note, however, that not all LoadingValueReference instances + // have isLoading()==true: LoadingValueReference has a subclass, ComputingValueReference, for + // which isLoading() is false!) However, that might change, and we already have a *test* + // implementation for which it doesn't hold. So we check instanceof to be safe. + if (valueReference instanceof LoadingValueReference) { + // We check whether the thread that is loading the entry is our current thread, which would + // mean that we are both loading and waiting for the entry. In this case, we fail fast + // instead of deadlocking. + checkState( + ((LoadingValueReference<K, V>) valueReference).getLoadingThread() + != Thread.currentThread(), + "Recursive load of: %s", + key); + } + // don't consider expiration as we're concurrent with loading try { V value = valueReference.waitForValue(); @@ -2220,7 +2231,11 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> } } - V compute(K key, int hash, BiFunction<? super K, ? super @Nullable V, ? extends V> function) { + @CheckForNull + V compute( + K key, + int hash, + BiFunction<? super K, ? super @Nullable V, ? extends @Nullable V> function) { ReferenceEntry<K, V> e; ValueReference<K, V> valueReference = null; ComputingValueReference<K, V> computingValueReference = null; @@ -3512,12 +3527,15 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> final SettableFuture<V> futureValue = SettableFuture.create(); final Stopwatch stopwatch = Stopwatch.createUnstarted(); + final Thread loadingThread; + public LoadingValueReference() { this(null); } - public LoadingValueReference(ValueReference<K, V> oldValue) { + public LoadingValueReference(@CheckForNull ValueReference<K, V> oldValue) { this.oldValue = (oldValue == null) ? LocalCache.unset() : oldValue; + this.loadingThread = Thread.currentThread(); } @Override @@ -3593,7 +3611,9 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> } } - public V compute(K key, BiFunction<? super K, ? super @Nullable V, ? extends V> function) { + @CheckForNull + public V compute( + K key, BiFunction<? super K, ? super @Nullable V, ? extends @Nullable V> function) { stopwatch.start(); V previousValue; try { @@ -3640,6 +3660,10 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> ReferenceQueue<V> queue, @CheckForNull V value, ReferenceEntry<K, V> entry) { return this; } + + Thread getLoadingThread() { + return this.loadingThread; + } } static class ComputingValueReference<K, V> extends LoadingValueReference<K, V> { @@ -4255,7 +4279,9 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> } @Override - public V compute(K key, BiFunction<? super K, ? super @Nullable V, ? extends V> function) { + @CheckForNull + public V compute( + K key, BiFunction<? super K, ? super @Nullable V, ? extends @Nullable V> function) { checkNotNull(key); checkNotNull(function); int hash = hash(key); @@ -4270,7 +4296,9 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> } @Override - public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> function) { + @CheckForNull + public V computeIfPresent( + K key, BiFunction<? super K, ? super V, ? extends @Nullable V> function) { checkNotNull(key); checkNotNull(function); return compute(key, (k, oldValue) -> (oldValue == null) ? null : function.apply(k, oldValue)); diff --git a/guava/src/com/google/common/collect/AbstractBiMap.java b/guava/src/com/google/common/collect/AbstractBiMap.java index 0563ea0e8..fab709a54 100644 --- a/guava/src/com/google/common/collect/AbstractBiMap.java +++ b/guava/src/com/google/common/collect/AbstractBiMap.java @@ -19,6 +19,7 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.NullnessCasts.uncheckedCastNullableTToT; +import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; @@ -502,7 +503,7 @@ abstract class AbstractBiMap<K extends @Nullable Object, V extends @Nullable Obj @SuppressWarnings("unchecked") // reading data stored by writeObject private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); - setInverse((AbstractBiMap<V, K>) stream.readObject()); + setInverse((AbstractBiMap<V, K>) requireNonNull(stream.readObject())); } @GwtIncompatible // Not needed in the emulated source. diff --git a/guava/src/com/google/common/collect/AbstractMapBasedMultimap.java b/guava/src/com/google/common/collect/AbstractMapBasedMultimap.java index 1e48281bf..d9108f16c 100644 --- a/guava/src/com/google/common/collect/AbstractMapBasedMultimap.java +++ b/guava/src/com/google/common/collect/AbstractMapBasedMultimap.java @@ -1063,7 +1063,7 @@ abstract class AbstractMapBasedMultimap<K extends @Nullable Object, V extends @N } @WeakOuter - class NavigableKeySet extends SortedKeySet implements NavigableSet<K> { + private final class NavigableKeySet extends SortedKeySet implements NavigableSet<K> { NavigableKeySet(NavigableMap<K, Collection<V>> subMap) { super(subMap); } @@ -1552,7 +1552,7 @@ abstract class AbstractMapBasedMultimap<K extends @Nullable Object, V extends @N } } - class NavigableAsMap extends SortedAsMap implements NavigableMap<K, Collection<V>> { + private final class NavigableAsMap extends SortedAsMap implements NavigableMap<K, Collection<V>> { NavigableAsMap(NavigableMap<K, Collection<V>> submap) { super(submap); diff --git a/guava/src/com/google/common/collect/CartesianList.java b/guava/src/com/google/common/collect/CartesianList.java index 4c31b1299..a93fb032f 100644 --- a/guava/src/com/google/common/collect/CartesianList.java +++ b/guava/src/com/google/common/collect/CartesianList.java @@ -17,6 +17,8 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkElementIndex; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.common.math.IntMath; import java.util.AbstractList; import java.util.List; @@ -132,6 +134,15 @@ final class CartesianList<E> extends AbstractList<List<E>> implements RandomAcce boolean isPartialView() { return true; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @J2ktIncompatible // serialization + @Override + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } }; } diff --git a/guava/src/com/google/common/collect/CollectCollectors.java b/guava/src/com/google/common/collect/CollectCollectors.java index e0982ab0f..2b23bd25a 100644 --- a/guava/src/com/google/common/collect/CollectCollectors.java +++ b/guava/src/com/google/common/collect/CollectCollectors.java @@ -195,14 +195,13 @@ final class CollectCollectors { ImmutableMap.Builder<K, V>::new, (builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)), ImmutableMap.Builder::combine, - ImmutableMap.Builder::build); + ImmutableMap.Builder::buildOrThrow); } - public static <T extends @Nullable Object, K, V> - Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( - Function<? super T, ? extends K> keyFunction, - Function<? super T, ? extends V> valueFunction, - BinaryOperator<V> mergeFunction) { + static <T extends @Nullable Object, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( + Function<? super T, ? extends K> keyFunction, + Function<? super T, ? extends V> valueFunction, + BinaryOperator<V> mergeFunction) { checkNotNull(keyFunction); checkNotNull(valueFunction); checkNotNull(mergeFunction); @@ -227,7 +226,7 @@ final class CollectCollectors { () -> new ImmutableSortedMap.Builder<K, V>(comparator), (builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)), ImmutableSortedMap.Builder::combine, - ImmutableSortedMap.Builder::build, + ImmutableSortedMap.Builder::buildOrThrow, Collector.Characteristics.UNORDERED); } @@ -256,7 +255,7 @@ final class CollectCollectors { ImmutableBiMap.Builder<K, V>::new, (builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)), ImmutableBiMap.Builder::combine, - ImmutableBiMap.Builder::build, + ImmutableBiMap.Builder::buildOrThrow, new Collector.Characteristics[0]); } @@ -464,4 +463,6 @@ final class CollectCollectors { return multimap1; }); } + + private CollectCollectors() {} } diff --git a/guava/src/com/google/common/collect/ConcurrentHashMultiset.java b/guava/src/com/google/common/collect/ConcurrentHashMultiset.java index 723ab0696..a84e3cee7 100644 --- a/guava/src/com/google/common/collect/ConcurrentHashMultiset.java +++ b/guava/src/com/google/common/collect/ConcurrentHashMultiset.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.CollectPreconditions.checkNonnegative; +import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; @@ -599,7 +600,7 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme stream.defaultReadObject(); @SuppressWarnings("unchecked") // reading data stored by writeObject ConcurrentMap<E, Integer> deserializedCountMap = - (ConcurrentMap<E, Integer>) stream.readObject(); + (ConcurrentMap<E, Integer>) requireNonNull(stream.readObject()); FieldSettersHolder.COUNT_MAP_FIELD_SETTER.set(this, deserializedCountMap); } diff --git a/guava/src/com/google/common/collect/ContiguousSet.java b/guava/src/com/google/common/collect/ContiguousSet.java index d0792054e..539c67383 100644 --- a/guava/src/com/google/common/collect/ContiguousSet.java +++ b/guava/src/com/google/common/collect/ContiguousSet.java @@ -20,6 +20,7 @@ import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.errorprone.annotations.DoNotCall; import java.util.Collections; import java.util.NoSuchElementException; @@ -259,4 +260,13 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte public static <E> ImmutableSortedSet.Builder<E> builder() { throw new UnsupportedOperationException(); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @J2ktIncompatible // serialization + @Override + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/DenseImmutableTable.java b/guava/src/com/google/common/collect/DenseImmutableTable.java index 9de77c57f..a8e96e382 100644 --- a/guava/src/com/google/common/collect/DenseImmutableTable.java +++ b/guava/src/com/google/common/collect/DenseImmutableTable.java @@ -17,6 +17,8 @@ package com.google.common.collect; import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.common.collect.ImmutableMap.IteratorBasedImmutableMap; import com.google.errorprone.annotations.Immutable; import com.google.j2objc.annotations.WeakOuter; @@ -144,6 +146,15 @@ final class DenseImmutableTable<R, C, V> extends RegularImmutableTable<R, C, V> } }; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @J2ktIncompatible // serialization + @Override + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } private final class Row extends ImmutableArrayMap<C, V> { @@ -169,6 +180,15 @@ final class DenseImmutableTable<R, C, V> extends RegularImmutableTable<R, C, V> boolean isPartialView() { return true; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } private final class Column extends ImmutableArrayMap<R, V> { @@ -194,6 +214,15 @@ final class DenseImmutableTable<R, C, V> extends RegularImmutableTable<R, C, V> boolean isPartialView() { return true; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } @WeakOuter @@ -216,6 +245,15 @@ final class DenseImmutableTable<R, C, V> extends RegularImmutableTable<R, C, V> boolean isPartialView() { return false; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } @WeakOuter @@ -238,6 +276,15 @@ final class DenseImmutableTable<R, C, V> extends RegularImmutableTable<R, C, V> boolean isPartialView() { return false; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } @Override @@ -285,7 +332,9 @@ final class DenseImmutableTable<R, C, V> extends RegularImmutableTable<R, C, V> } @Override - SerializedForm createSerializedForm() { + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { return SerializedForm.create(this, cellRowIndices, cellColumnIndices); } } diff --git a/guava/src/com/google/common/collect/DescendingImmutableSortedMultiset.java b/guava/src/com/google/common/collect/DescendingImmutableSortedMultiset.java index 181731cc4..931c3e72c 100644 --- a/guava/src/com/google/common/collect/DescendingImmutableSortedMultiset.java +++ b/guava/src/com/google/common/collect/DescendingImmutableSortedMultiset.java @@ -15,6 +15,7 @@ package com.google.common.collect; import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import javax.annotation.CheckForNull; /** @@ -83,4 +84,12 @@ final class DescendingImmutableSortedMultiset<E> extends ImmutableSortedMultiset boolean isPartialView() { return forward.isPartialView(); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/DescendingImmutableSortedSet.java b/guava/src/com/google/common/collect/DescendingImmutableSortedSet.java index 88c7d6b5c..10b3fa866 100644 --- a/guava/src/com/google/common/collect/DescendingImmutableSortedSet.java +++ b/guava/src/com/google/common/collect/DescendingImmutableSortedSet.java @@ -17,6 +17,7 @@ package com.google.common.collect; import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import javax.annotation.CheckForNull; /** @@ -121,4 +122,12 @@ final class DescendingImmutableSortedSet<E> extends ImmutableSortedSet<E> { boolean isPartialView() { return forward.isPartialView(); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/EnumBiMap.java b/guava/src/com/google/common/collect/EnumBiMap.java index c4b540b56..b7d297272 100644 --- a/guava/src/com/google/common/collect/EnumBiMap.java +++ b/guava/src/com/google/common/collect/EnumBiMap.java @@ -19,6 +19,7 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Platform.getDeclaringClassOrObjectForJ2cl; +import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; @@ -151,8 +152,8 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>> extends Abstr @GwtIncompatible // java.io.ObjectInputStream private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); - keyTypeOrObjectUnderJ2cl = (Class<K>) stream.readObject(); - valueTypeOrObjectUnderJ2cl = (Class<V>) stream.readObject(); + keyTypeOrObjectUnderJ2cl = (Class<K>) requireNonNull(stream.readObject()); + valueTypeOrObjectUnderJ2cl = (Class<V>) requireNonNull(stream.readObject()); setDelegates( new EnumMap<K, V>(keyTypeOrObjectUnderJ2cl), new EnumMap<V, K>(valueTypeOrObjectUnderJ2cl)); Serialization.populateMap(this, stream); diff --git a/guava/src/com/google/common/collect/EnumHashBiMap.java b/guava/src/com/google/common/collect/EnumHashBiMap.java index 33b45b95c..c7432d404 100644 --- a/guava/src/com/google/common/collect/EnumHashBiMap.java +++ b/guava/src/com/google/common/collect/EnumHashBiMap.java @@ -17,6 +17,7 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; @@ -128,7 +129,7 @@ public final class EnumHashBiMap<K extends Enum<K>, V extends @Nullable Object> @GwtIncompatible // java.io.ObjectInputStream private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); - keyTypeOrObjectUnderJ2cl = (Class<K>) stream.readObject(); + keyTypeOrObjectUnderJ2cl = (Class<K>) requireNonNull(stream.readObject()); /* * TODO: cpovirk - Pre-size the HashMap based on the number of enum values? (But *not* based on * the number of entries in the map, as that makes it easy for hostile inputs to trigger lots of diff --git a/guava/src/com/google/common/collect/EnumMultiset.java b/guava/src/com/google/common/collect/EnumMultiset.java index d6ced718b..04126f8aa 100644 --- a/guava/src/com/google/common/collect/EnumMultiset.java +++ b/guava/src/com/google/common/collect/EnumMultiset.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.CollectPreconditions.checkNonnegative; import static com.google.common.collect.CollectPreconditions.checkRemove; +import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; @@ -309,7 +310,7 @@ public final class EnumMultiset<E extends Enum<E>> extends AbstractMultiset<E> private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); @SuppressWarnings("unchecked") // reading data stored by writeObject - Class<E> localType = (Class<E>) stream.readObject(); + Class<E> localType = (Class<E>) requireNonNull(stream.readObject()); type = localType; enumConstants = type.getEnumConstants(); counts = new int[enumConstants.length]; diff --git a/guava/src/com/google/common/collect/HashBiMap.java b/guava/src/com/google/common/collect/HashBiMap.java index f6ce5d42b..066056774 100644 --- a/guava/src/com/google/common/collect/HashBiMap.java +++ b/guava/src/com/google/common/collect/HashBiMap.java @@ -90,7 +90,7 @@ public final class HashBiMap<K extends @Nullable Object, V extends @Nullable Obj return bimap; } - private static final class BiEntry<K extends @Nullable Object, V extends @Nullable Object> + static final class BiEntry<K extends @Nullable Object, V extends @Nullable Object> extends ImmutableEntry<K, V> { final int keyHash; final int valueHash; @@ -438,7 +438,7 @@ public final class HashBiMap<K extends @Nullable Object, V extends @Nullable Obj return size; } - abstract class Itr<T extends @Nullable Object> implements Iterator<T> { + private abstract class Itr<T extends @Nullable Object> implements Iterator<T> { @CheckForNull BiEntry<K, V> next = firstInKeyInsertionOrder; @CheckForNull BiEntry<K, V> toRemove = null; int expectedModCount = modCount; @@ -531,7 +531,7 @@ public final class HashBiMap<K extends @Nullable Object, V extends @Nullable Obj } class MapEntry extends AbstractMapEntry<K, V> { - BiEntry<K, V> delegate; + private BiEntry<K, V> delegate; MapEntry(BiEntry<K, V> entry) { this.delegate = entry; @@ -708,7 +708,7 @@ public final class HashBiMap<K extends @Nullable Object, V extends @Nullable Obj } class InverseEntry extends AbstractMapEntry<V, K> { - BiEntry<K, V> delegate; + private BiEntry<K, V> delegate; InverseEntry(BiEntry<K, V> entry) { this.delegate = entry; diff --git a/guava/src/com/google/common/collect/ImmutableBiMap.java b/guava/src/com/google/common/collect/ImmutableBiMap.java index c0d3ed715..f1777e62e 100644 --- a/guava/src/com/google/common/collect/ImmutableBiMap.java +++ b/guava/src/com/google/common/collect/ImmutableBiMap.java @@ -30,6 +30,7 @@ import java.io.ObjectInputStream; import java.util.Arrays; import java.util.Comparator; import java.util.Map; +import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.stream.Collector; import java.util.stream.Collectors; @@ -45,8 +46,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; */ @GwtCompatible(serializable = true, emulated = true) @ElementTypesAreNonnullByDefault -public abstract class ImmutableBiMap<K, V> extends ImmutableBiMapFauxverideShim<K, V> - implements BiMap<K, V> { +public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> implements BiMap<K, V> { /** * Returns a {@link Collector} that accumulates elements into an {@code ImmutableBiMap} whose keys @@ -642,4 +642,40 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableBiMapFauxverideShim< private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Use SerializedForm"); } + + /** + * Not supported. Use {@link #toImmutableBiMap} instead. This method exists only to hide {@link + * ImmutableMap#toImmutableMap(Function, Function)} from consumers of {@code ImmutableBiMap}. + * + * @throws UnsupportedOperationException always + * @deprecated Use {@link ImmutableBiMap#toImmutableBiMap}. + */ + @Deprecated + @DoNotCall("Use toImmutableBiMap") + public static <T extends @Nullable Object, K, V> + Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( + Function<? super T, ? extends K> keyFunction, + Function<? super T, ? extends V> valueFunction) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. This method does not make sense for {@code BiMap}. This method exists only to + * hide {@link ImmutableMap#toImmutableMap(Function, Function, BinaryOperator)} from consumers of + * {@code ImmutableBiMap}. + * + * @throws UnsupportedOperationException always + * @deprecated + */ + @Deprecated + @DoNotCall("Use toImmutableBiMap") + public static <T extends @Nullable Object, K, V> + Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( + Function<? super T, ? extends K> keyFunction, + Function<? super T, ? extends V> valueFunction, + BinaryOperator<V> mergeFunction) { + throw new UnsupportedOperationException(); + } + + private static final long serialVersionUID = 0xcafebabe; } diff --git a/guava/src/com/google/common/collect/ImmutableBiMapFauxverideShim.java b/guava/src/com/google/common/collect/ImmutableBiMapFauxverideShim.java deleted file mode 100644 index 2f1f25c82..000000000 --- a/guava/src/com/google/common/collect/ImmutableBiMapFauxverideShim.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2015 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.common.collect; - -import com.google.common.annotations.GwtIncompatible; -import com.google.errorprone.annotations.DoNotCall; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.stream.Collector; -import org.checkerframework.checker.nullness.qual.Nullable; - -/** - * "Overrides" the {@link ImmutableMap} static methods that lack {@link ImmutableBiMap} equivalents - * with deprecated, exception-throwing versions. See {@link ImmutableSortedSetFauxverideShim} for - * details. - * - * @author Louis Wasserman - */ -@GwtIncompatible -@ElementTypesAreNonnullByDefault -abstract class ImmutableBiMapFauxverideShim<K, V> extends ImmutableMap<K, V> { - /** - * Not supported. Use {@link ImmutableBiMap#toImmutableBiMap} instead. This method exists only to - * hide {@link ImmutableMap#toImmutableMap(Function, Function)} from consumers of {@code - * ImmutableBiMap}. - * - * @throws UnsupportedOperationException always - * @deprecated Use {@link ImmutableBiMap#toImmutableBiMap}. - */ - @Deprecated - @DoNotCall("Use toImmutableBiMap") - public static <T extends @Nullable Object, K, V> - Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( - Function<? super T, ? extends K> keyFunction, - Function<? super T, ? extends V> valueFunction) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. This method does not make sense for {@code BiMap}. This method exists only to - * hide {@link ImmutableMap#toImmutableMap(Function, Function, BinaryOperator)} from consumers of - * {@code ImmutableBiMap}. - * - * @throws UnsupportedOperationException always - * @deprecated - */ - @Deprecated - @DoNotCall("Use toImmutableBiMap") - public static <T extends @Nullable Object, K, V> - Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( - Function<? super T, ? extends K> keyFunction, - Function<? super T, ? extends V> valueFunction, - BinaryOperator<V> mergeFunction) { - throw new UnsupportedOperationException(); - } -} diff --git a/guava/src/com/google/common/collect/ImmutableCollection.java b/guava/src/com/google/common/collect/ImmutableCollection.java index 68b175ffa..ee18f0d9c 100644 --- a/guava/src/com/google/common/collect/ImmutableCollection.java +++ b/guava/src/com/google/common/collect/ImmutableCollection.java @@ -19,6 +19,7 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.DoNotCall; @@ -392,6 +393,7 @@ public abstract class ImmutableCollection<E> extends AbstractCollection<E> imple } @J2ktIncompatible // serialization + @GwtIncompatible // serialization Object writeReplace() { // We serialize by default to ImmutableList, the simplest thing that works. return new ImmutableList.SerializedForm(toArray()); @@ -504,4 +506,6 @@ public abstract class ImmutableCollection<E> extends AbstractCollection<E> imple */ public abstract ImmutableCollection<E> build(); } + + private static final long serialVersionUID = 0xcafebabe; } diff --git a/guava/src/com/google/common/collect/ImmutableList.java b/guava/src/com/google/common/collect/ImmutableList.java index 9c60caf3f..7c7801dbc 100644 --- a/guava/src/com/google/common/collect/ImmutableList.java +++ b/guava/src/com/google/common/collect/ImmutableList.java @@ -26,6 +26,7 @@ import static com.google.common.collect.RegularImmutableList.EMPTY; import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; import com.google.common.annotations.VisibleForTesting; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -444,6 +445,12 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E> * Returns an immutable list of the elements between the specified {@code fromIndex}, inclusive, * and {@code toIndex}, exclusive. (If {@code fromIndex} and {@code toIndex} are equal, the empty * immutable list is returned.) + * + * <p><b>Note:</b> in almost all circumstances, the returned {@link ImmutableList} retains a + * strong reference to {@code this}, which may prevent the original list from being garbage + * collected. If you want the original list to be eligible for garbage collection, you should + * create and use a copy of the sub list (e.g., {@code + * ImmutableList.copyOf(originalList.subList(...))}). */ @Override public ImmutableList<E> subList(int fromIndex, int toIndex) { @@ -498,6 +505,15 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E> boolean isPartialView() { return true; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } /** @@ -678,6 +694,15 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E> boolean isPartialView() { return forwardList.isPartialView(); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } @Override @@ -724,6 +749,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E> @Override @J2ktIncompatible // serialization + @GwtIncompatible // serialization Object writeReplace() { return new SerializedForm(toArray()); } @@ -901,4 +927,6 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E> return asImmutableList(contents, size); } } + + private static final long serialVersionUID = 0xcafebabe; } diff --git a/guava/src/com/google/common/collect/ImmutableListMultimap.java b/guava/src/com/google/common/collect/ImmutableListMultimap.java index b46e7ae40..e70927484 100644 --- a/guava/src/com/google/common/collect/ImmutableListMultimap.java +++ b/guava/src/com/google/common/collect/ImmutableListMultimap.java @@ -16,6 +16,8 @@ package com.google.common.collect; +import static java.util.Objects.requireNonNull; + import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; @@ -473,7 +475,7 @@ public class ImmutableListMultimap<K, V> extends ImmutableMultimap<K, V> int tmpSize = 0; for (int i = 0; i < keyCount; i++) { - Object key = stream.readObject(); + Object key = requireNonNull(stream.readObject()); int valueCount = stream.readInt(); if (valueCount <= 0) { throw new InvalidObjectException("Invalid value count " + valueCount); @@ -481,7 +483,7 @@ public class ImmutableListMultimap<K, V> extends ImmutableMultimap<K, V> ImmutableList.Builder<Object> valuesBuilder = ImmutableList.builder(); for (int j = 0; j < valueCount; j++) { - valuesBuilder.add(stream.readObject()); + valuesBuilder.add(requireNonNull(stream.readObject())); } builder.put(key, valuesBuilder.build()); tmpSize += valueCount; diff --git a/guava/src/com/google/common/collect/ImmutableMap.java b/guava/src/com/google/common/collect/ImmutableMap.java index c370e5248..7a185b5d3 100644 --- a/guava/src/com/google/common/collect/ImmutableMap.java +++ b/guava/src/com/google/common/collect/ImmutableMap.java @@ -23,6 +23,7 @@ import static com.google.common.collect.CollectPreconditions.checkNonnegative; import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; import com.google.common.annotations.VisibleForTesting; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -96,8 +97,11 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable { * and values are the result of applying the provided mapping functions to the input elements. * * <p>If the mapped keys contain duplicates (according to {@link Object#equals(Object)}), the - * values are merged using the specified merging function. Entries will appear in the encounter - * order of the first occurrence of the key. + * values are merged using the specified merging function. If the merging function returns {@code + * null}, then the collector removes the value that has been computed for the key thus far (though + * future occurrences of the key would reinsert it). + * + * <p>Entries will appear in the encounter order of the first occurrence of the key. * * @since 21.0 */ @@ -754,6 +758,15 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable { public UnmodifiableIterator<Entry<K, V>> iterator() { return entryIterator(); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } return new EntrySetImpl(); } @@ -762,6 +775,15 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable { ImmutableCollection<V> createValues() { return new ImmutableMapValues<>(this); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } ImmutableMap() {} @@ -845,8 +867,9 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable { @Deprecated @Override @DoNotCall("Always throws UnsupportedOperationException") + @CheckForNull public final V computeIfPresent( - K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + K key, BiFunction<? super K, ? super V, ? extends @Nullable V> remappingFunction) { throw new UnsupportedOperationException(); } @@ -859,8 +882,9 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable { @Deprecated @Override @DoNotCall("Always throws UnsupportedOperationException") + @CheckForNull public final V compute( - K key, BiFunction<? super K, ? super @Nullable V, ? extends V> remappingFunction) { + K key, BiFunction<? super K, ? super @Nullable V, ? extends @Nullable V> remappingFunction) { throw new UnsupportedOperationException(); } @@ -1165,6 +1189,15 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable { } }; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } @Override @@ -1282,4 +1315,6 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable { private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Use SerializedForm"); } + + private static final long serialVersionUID = 0xcafebabe; } diff --git a/guava/src/com/google/common/collect/ImmutableMapEntrySet.java b/guava/src/com/google/common/collect/ImmutableMapEntrySet.java index 46df158b0..19f75cbbb 100644 --- a/guava/src/com/google/common/collect/ImmutableMapEntrySet.java +++ b/guava/src/com/google/common/collect/ImmutableMapEntrySet.java @@ -80,6 +80,15 @@ abstract class ImmutableMapEntrySet<K, V> extends ImmutableSet.CachingAsList<Ent ImmutableList<Entry<K, V>> createAsList() { return new RegularImmutableAsList<>(this, entries); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } ImmutableMapEntrySet() {} diff --git a/guava/src/com/google/common/collect/ImmutableMapKeySet.java b/guava/src/com/google/common/collect/ImmutableMapKeySet.java index 6d1b51671..fb2661f47 100644 --- a/guava/src/com/google/common/collect/ImmutableMapKeySet.java +++ b/guava/src/com/google/common/collect/ImmutableMapKeySet.java @@ -77,6 +77,15 @@ final class ImmutableMapKeySet<K, V> extends IndexedImmutableSet<K> { return true; } + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } + // No longer used for new writes, but kept so that old data can still be read. @GwtIncompatible // serialization @J2ktIncompatible diff --git a/guava/src/com/google/common/collect/ImmutableMapValues.java b/guava/src/com/google/common/collect/ImmutableMapValues.java index 8884c1af6..831364599 100644 --- a/guava/src/com/google/common/collect/ImmutableMapValues.java +++ b/guava/src/com/google/common/collect/ImmutableMapValues.java @@ -92,6 +92,15 @@ final class ImmutableMapValues<K, V> extends ImmutableCollection<V> { ImmutableCollection<V> delegateCollection() { return ImmutableMapValues.this; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } }; } @@ -102,6 +111,15 @@ final class ImmutableMapValues<K, V> extends ImmutableCollection<V> { map.forEach((k, v) -> action.accept(v)); } + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } + // No longer used for new writes, but kept so that old data can still be read. @GwtIncompatible // serialization @J2ktIncompatible diff --git a/guava/src/com/google/common/collect/ImmutableMultimap.java b/guava/src/com/google/common/collect/ImmutableMultimap.java index f1f654645..02dbd5e67 100644 --- a/guava/src/com/google/common/collect/ImmutableMultimap.java +++ b/guava/src/com/google/common/collect/ImmutableMultimap.java @@ -578,6 +578,15 @@ public abstract class ImmutableMultimap<K, V> extends BaseImmutableMultimap<K, V return false; } + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } + private static final long serialVersionUID = 0; } @@ -781,6 +790,15 @@ public abstract class ImmutableMultimap<K, V> extends BaseImmutableMultimap<K, V return true; } + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } + @J2ktIncompatible // serialization private static final long serialVersionUID = 0; } diff --git a/guava/src/com/google/common/collect/ImmutableMultiset.java b/guava/src/com/google/common/collect/ImmutableMultiset.java index cdc9f405a..f0197433f 100644 --- a/guava/src/com/google/common/collect/ImmutableMultiset.java +++ b/guava/src/com/google/common/collect/ImmutableMultiset.java @@ -630,6 +630,15 @@ public abstract class ImmutableMultiset<E> extends ImmutableMultisetGwtSerializa public int size() { return entries.size(); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } @J2ktIncompatible @@ -660,4 +669,6 @@ public abstract class ImmutableMultiset<E> extends ImmutableMultisetGwtSerializa private static final long serialVersionUID = 0; } + + private static final long serialVersionUID = 0xcafebabe; } diff --git a/guava/src/com/google/common/collect/ImmutableRangeMap.java b/guava/src/com/google/common/collect/ImmutableRangeMap.java index 72444245f..88ad7d889 100644 --- a/guava/src/com/google/common/collect/ImmutableRangeMap.java +++ b/guava/src/com/google/common/collect/ImmutableRangeMap.java @@ -372,6 +372,14 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K boolean isPartialView() { return true; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } }; final ImmutableRangeMap<K, V> outer = this; return new ImmutableRangeMap<K, V>(subRanges, values.subList(lowerIndex, upperIndex)) { @@ -383,6 +391,14 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K return ImmutableRangeMap.of(); } } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } }; } diff --git a/guava/src/com/google/common/collect/ImmutableRangeSet.java b/guava/src/com/google/common/collect/ImmutableRangeSet.java index afd421cd7..165b6e652 100644 --- a/guava/src/com/google/common/collect/ImmutableRangeSet.java +++ b/guava/src/com/google/common/collect/ImmutableRangeSet.java @@ -368,6 +368,14 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange boolean isPartialView() { return true; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } @Override @@ -487,6 +495,15 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange boolean isPartialView() { return true; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } }; } } diff --git a/guava/src/com/google/common/collect/ImmutableSet.java b/guava/src/com/google/common/collect/ImmutableSet.java index f4912a328..eeed833bf 100644 --- a/guava/src/com/google/common/collect/ImmutableSet.java +++ b/guava/src/com/google/common/collect/ImmutableSet.java @@ -22,6 +22,7 @@ import static com.google.common.collect.CollectPreconditions.checkNonnegative; import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; import com.google.common.annotations.VisibleForTesting; import com.google.common.math.IntMath; @@ -354,6 +355,15 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements ImmutableList<E> createAsList() { return new RegularImmutableAsList<E>(this, toArray()); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } abstract static class Indexed<E> extends CachingAsList<E> { @@ -395,8 +405,26 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements Indexed<E> delegateCollection() { return Indexed.this; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } }; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } /* @@ -989,4 +1017,6 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements } } } + + private static final long serialVersionUID = 0xcafebabe; } diff --git a/guava/src/com/google/common/collect/ImmutableSetMultimap.java b/guava/src/com/google/common/collect/ImmutableSetMultimap.java index 4887ae79b..b1f8438cd 100644 --- a/guava/src/com/google/common/collect/ImmutableSetMultimap.java +++ b/guava/src/com/google/common/collect/ImmutableSetMultimap.java @@ -17,6 +17,7 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; @@ -552,6 +553,15 @@ public class ImmutableSetMultimap<K, V> extends ImmutableMultimap<K, V> boolean isPartialView() { return false; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } private static <V> ImmutableSet<V> valueSet( @@ -615,7 +625,7 @@ public class ImmutableSetMultimap<K, V> extends ImmutableMultimap<K, V> int tmpSize = 0; for (int i = 0; i < keyCount; i++) { - Object key = stream.readObject(); + Object key = requireNonNull(stream.readObject()); int valueCount = stream.readInt(); if (valueCount <= 0) { throw new InvalidObjectException("Invalid value count " + valueCount); @@ -623,7 +633,7 @@ public class ImmutableSetMultimap<K, V> extends ImmutableMultimap<K, V> ImmutableSet.Builder<Object> valuesBuilder = valuesBuilder(valueComparator); for (int j = 0; j < valueCount; j++) { - valuesBuilder.add(stream.readObject()); + valuesBuilder.add(requireNonNull(stream.readObject())); } ImmutableSet<Object> valueSet = valuesBuilder.build(); if (valueSet.size() != valueCount) { diff --git a/guava/src/com/google/common/collect/ImmutableSortedAsList.java b/guava/src/com/google/common/collect/ImmutableSortedAsList.java index 30f19a02e..1736f2b8e 100644 --- a/guava/src/com/google/common/collect/ImmutableSortedAsList.java +++ b/guava/src/com/google/common/collect/ImmutableSortedAsList.java @@ -16,6 +16,7 @@ package com.google.common.collect; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import java.util.Comparator; import java.util.Spliterator; import javax.annotation.CheckForNull; @@ -93,4 +94,13 @@ final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E> delegateList()::get, comparator()); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/ImmutableSortedMap.java b/guava/src/com/google/common/collect/ImmutableSortedMap.java index f38922e43..ba0b91c95 100644 --- a/guava/src/com/google/common/collect/ImmutableSortedMap.java +++ b/guava/src/com/google/common/collect/ImmutableSortedMap.java @@ -23,6 +23,7 @@ import static com.google.common.collect.Maps.keyOrNull; import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.DoNotCall; @@ -64,7 +65,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; */ @GwtCompatible(serializable = true, emulated = true) @ElementTypesAreNonnullByDefault -public final class ImmutableSortedMap<K, V> extends ImmutableSortedMapFauxverideShim<K, V> +public final class ImmutableSortedMap<K, V> extends ImmutableMap<K, V> implements NavigableMap<K, V> { /** * Returns a {@link Collector} that accumulates elements into an {@code ImmutableSortedMap} whose @@ -844,6 +845,15 @@ public final class ImmutableSortedMap<K, V> extends ImmutableSortedMapFauxveride ImmutableCollection<Entry<K, V>> delegateCollection() { return EntrySet.this; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } }; } @@ -851,6 +861,15 @@ public final class ImmutableSortedMap<K, V> extends ImmutableSortedMapFauxveride ImmutableMap<K, V> map() { return ImmutableSortedMap.this; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } return isEmpty() ? ImmutableSet.<Entry<K, V>>of() : new EntrySet(); } @@ -1167,4 +1186,290 @@ public final class ImmutableSortedMap<K, V> extends ImmutableSortedMapFauxveride // This class is never actually serialized directly, but we have to make the // warning go away (and suppressing would suppress for all nested classes too) private static final long serialVersionUID = 0; + + /** + * Not supported. Use {@link #toImmutableSortedMap}, which offers better type-safety, instead. + * This method exists only to hide {@link ImmutableMap#toImmutableMap} from consumers of {@code + * ImmutableSortedMap}. + * + * @throws UnsupportedOperationException always + * @deprecated Use {@link ImmutableSortedMap#toImmutableSortedMap}. + */ + @DoNotCall("Use toImmutableSortedMap") + @Deprecated + public static <T extends @Nullable Object, K, V> + Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( + Function<? super T, ? extends K> keyFunction, + Function<? super T, ? extends V> valueFunction) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. Use {@link #toImmutableSortedMap}, which offers better type-safety, instead. + * This method exists only to hide {@link ImmutableMap#toImmutableMap} from consumers of {@code + * ImmutableSortedMap}. + * + * @throws UnsupportedOperationException always + * @deprecated Use {@link ImmutableSortedMap#toImmutableSortedMap}. + */ + @DoNotCall("Use toImmutableSortedMap") + @Deprecated + public static <T extends @Nullable Object, K, V> + Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( + Function<? super T, ? extends K> keyFunction, + Function<? super T, ? extends V> valueFunction, + BinaryOperator<V> mergeFunction) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. Use {@link #naturalOrder}, which offers better type-safety, instead. This method + * exists only to hide {@link ImmutableMap#builder} from consumers of {@code ImmutableSortedMap}. + * + * @throws UnsupportedOperationException always + * @deprecated Use {@link ImmutableSortedMap#naturalOrder}, which offers better type-safety. + */ + @DoNotCall("Use naturalOrder") + @Deprecated + public static <K, V> ImmutableSortedMap.Builder<K, V> builder() { + throw new UnsupportedOperationException(); + } + + /** + * Not supported for ImmutableSortedMap. + * + * @throws UnsupportedOperationException always + * @deprecated Not supported for ImmutableSortedMap. + */ + @DoNotCall("Use naturalOrder (which does not accept an expected size)") + @Deprecated + public static <K, V> ImmutableSortedMap.Builder<K, V> builderWithExpectedSize(int expectedSize) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a map that may contain a non-{@code Comparable} + * key.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this dummy + * version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass a key of type {@code Comparable} to use {@link + * ImmutableSortedMap#of(Comparable, Object)}.</b> + */ + @DoNotCall("Pass a key of type Comparable") + @Deprecated + public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} + * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass keys of type {@code Comparable} to use {@link + * ImmutableSortedMap#of(Comparable, Object, Comparable, Object)}.</b> + */ + @DoNotCall("Pass keys of type Comparable") + @Deprecated + public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} + * keys.</b> Proper calls to will resolve to the version in {@code ImmutableSortedMap}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass keys of type {@code Comparable} to use {@link + * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object)}.</b> + */ + @DoNotCall("Pass keys of type Comparable") + @Deprecated + public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} + * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass keys of type {@code Comparable} to use {@link + * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, + * Comparable, Object)}.</b> + */ + @DoNotCall("Pass keys of type Comparable") + @Deprecated + public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} + * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass keys of type {@code Comparable} to use {@link + * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, + * Comparable, Object, Comparable, Object)}.</b> + */ + @DoNotCall("Pass keys of type Comparable") + @Deprecated + public static <K, V> ImmutableSortedMap<K, V> of( + K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} + * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass keys of type {@code Comparable} to use {@link + * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, + * Comparable, Object, Comparable, Object)}.</b> + */ + @DoNotCall("Pass keys of type Comparable") + @Deprecated + public static <K, V> ImmutableSortedMap<K, V> of( + K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} + * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass keys of type {@code Comparable} to use {@link + * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, + * Comparable, Object, Comparable, Object)}.</b> + */ + @DoNotCall("Pass keys of type Comparable") + @Deprecated + public static <K, V> ImmutableSortedMap<K, V> of( + K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} + * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass keys of type {@code Comparable} to use {@link + * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, + * Comparable, Object, Comparable, Object)}.</b> + */ + @DoNotCall("Pass keys of type Comparable") + @Deprecated + public static <K, V> ImmutableSortedMap<K, V> of( + K k1, + V v1, + K k2, + V v2, + K k3, + V v3, + K k4, + V v4, + K k5, + V v5, + K k6, + V v6, + K k7, + V v7, + K k8, + V v8) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} + * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass keys of type {@code Comparable} to use {@link + * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, + * Comparable, Object, Comparable, Object)}.</b> + */ + @DoNotCall("Pass keys of type Comparable") + @Deprecated + public static <K, V> ImmutableSortedMap<K, V> of( + K k1, + V v1, + K k2, + V v2, + K k3, + V v3, + K k4, + V v4, + K k5, + V v5, + K k6, + V v6, + K k7, + V v7, + K k8, + V v8, + K k9, + V v9) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} + * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass keys of type {@code Comparable} to use {@link + * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, + * Comparable, Object, Comparable, Object)}.</b> + */ + @DoNotCall("Pass keys of type Comparable") + @Deprecated + public static <K, V> ImmutableSortedMap<K, V> of( + K k1, + V v1, + K k2, + V v2, + K k3, + V v3, + K k4, + V v4, + K k5, + V v5, + K k6, + V v6, + K k7, + V v7, + K k8, + V v8, + K k9, + V v9, + K k10, + V v10) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. Use {@code ImmutableSortedMap.copyOf(ImmutableMap.ofEntries(...))}. + * + * @deprecated Use {@code ImmutableSortedMap.copyOf(ImmutableMap.ofEntries(...))}. + */ + @DoNotCall("ImmutableSortedMap.ofEntries not currently available; use ImmutableSortedMap.copyOf") + @Deprecated + public static <K, V> ImmutableSortedMap<K, V> ofEntries( + Entry<? extends K, ? extends V>... entries) { + throw new UnsupportedOperationException(); + } } diff --git a/guava/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java b/guava/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java deleted file mode 100644 index 7b2e4d755..000000000 --- a/guava/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (C) 2009 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.common.collect; - -import com.google.common.annotations.GwtIncompatible; -import com.google.errorprone.annotations.DoNotCall; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.stream.Collector; -import org.checkerframework.checker.nullness.qual.Nullable; - -/** - * "Overrides" the {@link ImmutableMap} static methods that lack {@link ImmutableSortedMap} - * equivalents with deprecated, exception-throwing versions. See {@link - * ImmutableSortedSetFauxverideShim} for details. - * - * @author Chris Povirk - */ -@GwtIncompatible -@ElementTypesAreNonnullByDefault -abstract class ImmutableSortedMapFauxverideShim<K, V> extends ImmutableMap<K, V> { - /** - * Not supported. Use {@link ImmutableSortedMap#toImmutableSortedMap}, which offers better - * type-safety, instead. This method exists only to hide {@link ImmutableMap#toImmutableMap} from - * consumers of {@code ImmutableSortedMap}. - * - * @throws UnsupportedOperationException always - * @deprecated Use {@link ImmutableSortedMap#toImmutableSortedMap}. - */ - @DoNotCall("Use toImmutableSortedMap") - @Deprecated - public static <T extends @Nullable Object, K, V> - Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( - Function<? super T, ? extends K> keyFunction, - Function<? super T, ? extends V> valueFunction) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. Use {@link ImmutableSortedMap#toImmutableSortedMap}, which offers better - * type-safety, instead. This method exists only to hide {@link ImmutableMap#toImmutableMap} from - * consumers of {@code ImmutableSortedMap}. - * - * @throws UnsupportedOperationException always - * @deprecated Use {@link ImmutableSortedMap#toImmutableSortedMap}. - */ - @DoNotCall("Use toImmutableSortedMap") - @Deprecated - public static <T extends @Nullable Object, K, V> - Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( - Function<? super T, ? extends K> keyFunction, - Function<? super T, ? extends V> valueFunction, - BinaryOperator<V> mergeFunction) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. Use {@link ImmutableSortedMap#naturalOrder}, which offers better type-safety, - * instead. This method exists only to hide {@link ImmutableMap#builder} from consumers of {@code - * ImmutableSortedMap}. - * - * @throws UnsupportedOperationException always - * @deprecated Use {@link ImmutableSortedMap#naturalOrder}, which offers better type-safety. - */ - @DoNotCall("Use naturalOrder") - @Deprecated - public static <K, V> ImmutableSortedMap.Builder<K, V> builder() { - throw new UnsupportedOperationException(); - } - - /** - * Not supported for ImmutableSortedMap. - * - * @throws UnsupportedOperationException always - * @deprecated Not supported for ImmutableSortedMap. - */ - @DoNotCall("Use naturalOrder (which does not accept an expected size)") - @Deprecated - public static <K, V> ImmutableSortedMap.Builder<K, V> builderWithExpectedSize(int expectedSize) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a map that may contain a non-{@code Comparable} - * key.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this dummy - * version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass a key of type {@code Comparable} to use {@link - * ImmutableSortedMap#of(Comparable, Object)}.</b> - */ - @DoNotCall("Pass a key of type Comparable") - @Deprecated - public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} - * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass keys of type {@code Comparable} to use {@link - * ImmutableSortedMap#of(Comparable, Object, Comparable, Object)}.</b> - */ - @DoNotCall("Pass keys of type Comparable") - @Deprecated - public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} - * keys.</b> Proper calls to will resolve to the version in {@code ImmutableSortedMap}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass keys of type {@code Comparable} to use {@link - * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object)}.</b> - */ - @DoNotCall("Pass keys of type Comparable") - @Deprecated - public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} - * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass keys of type {@code Comparable} to use {@link - * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, - * Comparable, Object)}.</b> - */ - @DoNotCall("Pass keys of type Comparable") - @Deprecated - public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} - * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass keys of type {@code Comparable} to use {@link - * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, - * Comparable, Object, Comparable, Object)}.</b> - */ - @DoNotCall("Pass keys of type Comparable") - @Deprecated - public static <K, V> ImmutableSortedMap<K, V> of( - K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} - * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass keys of type {@code Comparable} to use {@link - * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, - * Comparable, Object, Comparable, Object)}.</b> - */ - @DoNotCall("Pass keys of type Comparable") - @Deprecated - public static <K, V> ImmutableSortedMap<K, V> of( - K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} - * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass keys of type {@code Comparable} to use {@link - * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, - * Comparable, Object, Comparable, Object)}.</b> - */ - @DoNotCall("Pass keys of type Comparable") - @Deprecated - public static <K, V> ImmutableSortedMap<K, V> of( - K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} - * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass keys of type {@code Comparable} to use {@link - * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, - * Comparable, Object, Comparable, Object)}.</b> - */ - @DoNotCall("Pass keys of type Comparable") - @Deprecated - public static <K, V> ImmutableSortedMap<K, V> of( - K k1, - V v1, - K k2, - V v2, - K k3, - V v3, - K k4, - V v4, - K k5, - V v5, - K k6, - V v6, - K k7, - V v7, - K k8, - V v8) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} - * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass keys of type {@code Comparable} to use {@link - * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, - * Comparable, Object, Comparable, Object)}.</b> - */ - @DoNotCall("Pass keys of type Comparable") - @Deprecated - public static <K, V> ImmutableSortedMap<K, V> of( - K k1, - V v1, - K k2, - V v2, - K k3, - V v3, - K k4, - V v4, - K k5, - V v5, - K k6, - V v6, - K k7, - V v7, - K k8, - V v8, - K k9, - V v9) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a map that may contain non-{@code Comparable} - * keys.</b> Proper calls will resolve to the version in {@code ImmutableSortedMap}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass keys of type {@code Comparable} to use {@link - * ImmutableSortedMap#of(Comparable, Object, Comparable, Object, Comparable, Object, - * Comparable, Object, Comparable, Object)}.</b> - */ - @DoNotCall("Pass keys of type Comparable") - @Deprecated - public static <K, V> ImmutableSortedMap<K, V> of( - K k1, - V v1, - K k2, - V v2, - K k3, - V v3, - K k4, - V v4, - K k5, - V v5, - K k6, - V v6, - K k7, - V v7, - K k8, - V v8, - K k9, - V v9, - K k10, - V v10) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. Use {@code ImmutableSortedMap.copyOf(ImmutableMap.ofEntries(...))}. - * - * @deprecated Use {@code ImmutableSortedMap.copyOf(ImmutableMap.ofEntries(...))}. - */ - @DoNotCall("ImmutableSortedMap.ofEntries not currently available; use ImmutableSortedMap.copyOf") - @Deprecated - public static <K, V> ImmutableSortedMap<K, V> ofEntries( - Entry<? extends K, ? extends V>... entries) { - throw new UnsupportedOperationException(); - } - - // No copyOf() fauxveride; see ImmutableSortedSetFauxverideShim. -} diff --git a/guava/src/com/google/common/collect/ImmutableSortedMultiset.java b/guava/src/com/google/common/collect/ImmutableSortedMultiset.java index d2991bce9..454a77569 100644 --- a/guava/src/com/google/common/collect/ImmutableSortedMultiset.java +++ b/guava/src/com/google/common/collect/ImmutableSortedMultiset.java @@ -55,7 +55,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; */ @GwtIncompatible // hasn't been tested yet @ElementTypesAreNonnullByDefault -public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultisetFauxverideShim<E> +public abstract class ImmutableSortedMultiset<E> extends ImmutableMultiset<E> implements SortedMultiset<E> { // TODO(lowasser): GWT compatibility @@ -606,4 +606,162 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Use SerializedForm"); } + + /** + * Not supported. Use {@link #toImmutableSortedMultiset} instead. This method exists only to hide + * {@link ImmutableMultiset#toImmutableMultiset} from consumers of {@code + * ImmutableSortedMultiset}. + * + * @throws UnsupportedOperationException always + * @deprecated Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset}. + * @since 21.0 + */ + @DoNotCall("Use toImmutableSortedMultiset.") + @Deprecated + public static <E> Collector<E, ?, ImmutableMultiset<E>> toImmutableMultiset() { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. Use {@link #toImmutableSortedMultiset} instead. This method exists only to hide + * {@link ImmutableMultiset#toImmutableMultiset} from consumers of {@code + * ImmutableSortedMultiset}. + * + * @throws UnsupportedOperationException always + * @deprecated Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset}. + * @since 22.0 + */ + @DoNotCall("Use toImmutableSortedMultiset.") + @Deprecated + public static <T extends @Nullable Object, E> + Collector<T, ?, ImmutableMultiset<E>> toImmutableMultiset( + Function<? super T, ? extends E> elementFunction, + ToIntFunction<? super T> countFunction) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. Use {@link #naturalOrder}, which offers better type-safety, instead. This method + * exists only to hide {@link ImmutableMultiset#builder} from consumers of {@code + * ImmutableSortedMultiset}. + * + * @throws UnsupportedOperationException always + * @deprecated Use {@link ImmutableSortedMultiset#naturalOrder}, which offers better type-safety. + */ + @DoNotCall("Use naturalOrder.") + @Deprecated + public static <E> ImmutableSortedMultiset.Builder<E> builder() { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code + * Comparable} element.</b> Proper calls will resolve to the version in {@code + * ImmutableSortedMultiset}, not this dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass a parameter of type {@code Comparable} to use {@link + * ImmutableSortedMultiset#of(Comparable)}.</b> + */ + @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") + @Deprecated + public static <E> ImmutableSortedMultiset<E> of(E element) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code + * Comparable} element.</b> Proper calls will resolve to the version in {@code + * ImmutableSortedMultiset}, not this dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link + * ImmutableSortedMultiset#of(Comparable, Comparable)}.</b> + */ + @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") + @Deprecated + public static <E> ImmutableSortedMultiset<E> of(E e1, E e2) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code + * Comparable} element.</b> Proper calls will resolve to the version in {@code + * ImmutableSortedMultiset}, not this dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link + * ImmutableSortedMultiset#of(Comparable, Comparable, Comparable)}.</b> + */ + @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") + @Deprecated + public static <E> ImmutableSortedMultiset<E> of(E e1, E e2, E e3) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code + * Comparable} element.</b> Proper calls will resolve to the version in {@code + * ImmutableSortedMultiset}, not this dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link + * ImmutableSortedMultiset#of(Comparable, Comparable, Comparable, Comparable)}. </b> + */ + @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") + @Deprecated + public static <E> ImmutableSortedMultiset<E> of(E e1, E e2, E e3, E e4) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code + * Comparable} element.</b> Proper calls will resolve to the version in {@code + * ImmutableSortedMultiset}, not this dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link + * ImmutableSortedMultiset#of(Comparable, Comparable, Comparable, Comparable, Comparable)} . + * </b> + */ + @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") + @Deprecated + public static <E> ImmutableSortedMultiset<E> of(E e1, E e2, E e3, E e4, E e5) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code + * Comparable} element.</b> Proper calls will resolve to the version in {@code + * ImmutableSortedMultiset}, not this dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link + * ImmutableSortedMultiset#of(Comparable, Comparable, Comparable, Comparable, Comparable, + * Comparable, Comparable...)} . </b> + */ + @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") + @Deprecated + public static <E> ImmutableSortedMultiset<E> of( + E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a multiset that may contain non-{@code + * Comparable} elements.</b> Proper calls will resolve to the version in {@code + * ImmutableSortedMultiset}, not this dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass parameters of type {@code Comparable} to use {@link + * ImmutableSortedMultiset#copyOf(Comparable[])}.</b> + */ + @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") + @Deprecated + // The usage of "Z" here works around bugs in Javadoc (JDK-8318093) and JDiff. + public static <Z> ImmutableSortedMultiset<Z> copyOf(Z[] elements) { + throw new UnsupportedOperationException(); + } + + private static final long serialVersionUID = 0xcafebabe; } diff --git a/guava/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java b/guava/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java deleted file mode 100644 index 94a2f560d..000000000 --- a/guava/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2011 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.common.collect; - -import com.google.common.annotations.GwtIncompatible; -import com.google.errorprone.annotations.DoNotCall; -import java.util.function.Function; -import java.util.function.ToIntFunction; -import java.util.stream.Collector; -import org.checkerframework.checker.nullness.qual.Nullable; - -/** - * "Overrides" the {@link ImmutableMultiset} static methods that lack {@link - * ImmutableSortedMultiset} equivalents with deprecated, exception-throwing versions. This prevents - * accidents like the following: - * - * <pre>{@code - * List<Object> objects = ...; - * // Sort them: - * Set<Object> sorted = ImmutableSortedMultiset.copyOf(objects); - * // BAD CODE! The returned multiset is actually an unsorted ImmutableMultiset! - * }</pre> - * - * <p>While we could put the overrides in {@link ImmutableSortedMultiset} itself, it seems clearer - * to separate these "do not call" methods from those intended for normal use. - * - * @author Louis Wasserman - */ -@GwtIncompatible -@ElementTypesAreNonnullByDefault -abstract class ImmutableSortedMultisetFauxverideShim<E> extends ImmutableMultiset<E> { - /** - * Not supported. Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset} instead. This - * method exists only to hide {@link ImmutableMultiset#toImmutableMultiset} from consumers of - * {@code ImmutableSortedMultiset}. - * - * @throws UnsupportedOperationException always - * @deprecated Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset}. - * @since 21.0 - */ - @DoNotCall("Use toImmutableSortedMultiset.") - @Deprecated - public static <E> Collector<E, ?, ImmutableMultiset<E>> toImmutableMultiset() { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset} instead. This - * method exists only to hide {@link ImmutableMultiset#toImmutableMultiset} from consumers of - * {@code ImmutableSortedMultiset}. - * - * @throws UnsupportedOperationException always - * @deprecated Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset}. - * @since 22.0 - */ - @DoNotCall("Use toImmutableSortedMultiset.") - @Deprecated - public static <T extends @Nullable Object, E> - Collector<T, ?, ImmutableMultiset<E>> toImmutableMultiset( - Function<? super T, ? extends E> elementFunction, - ToIntFunction<? super T> countFunction) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. Use {@link ImmutableSortedMultiset#naturalOrder}, which offers better - * type-safety, instead. This method exists only to hide {@link ImmutableMultiset#builder} from - * consumers of {@code ImmutableSortedMultiset}. - * - * @throws UnsupportedOperationException always - * @deprecated Use {@link ImmutableSortedMultiset#naturalOrder}, which offers better type-safety. - */ - @DoNotCall("Use naturalOrder.") - @Deprecated - public static <E> ImmutableSortedMultiset.Builder<E> builder() { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code - * Comparable} element.</b> Proper calls will resolve to the version in {@code - * ImmutableSortedMultiset}, not this dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass a parameter of type {@code Comparable} to use {@link - * ImmutableSortedMultiset#of(Comparable)}.</b> - */ - @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") - @Deprecated - public static <E> ImmutableSortedMultiset<E> of(E element) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code - * Comparable} element.</b> Proper calls will resolve to the version in {@code - * ImmutableSortedMultiset}, not this dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link - * ImmutableSortedMultiset#of(Comparable, Comparable)}.</b> - */ - @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") - @Deprecated - public static <E> ImmutableSortedMultiset<E> of(E e1, E e2) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code - * Comparable} element.</b> Proper calls will resolve to the version in {@code - * ImmutableSortedMultiset}, not this dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link - * ImmutableSortedMultiset#of(Comparable, Comparable, Comparable)}.</b> - */ - @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") - @Deprecated - public static <E> ImmutableSortedMultiset<E> of(E e1, E e2, E e3) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code - * Comparable} element.</b> Proper calls will resolve to the version in {@code - * ImmutableSortedMultiset}, not this dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link - * ImmutableSortedMultiset#of(Comparable, Comparable, Comparable, Comparable)}. </b> - */ - @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") - @Deprecated - public static <E> ImmutableSortedMultiset<E> of(E e1, E e2, E e3, E e4) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code - * Comparable} element.</b> Proper calls will resolve to the version in {@code - * ImmutableSortedMultiset}, not this dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link - * ImmutableSortedMultiset#of(Comparable, Comparable, Comparable, Comparable, Comparable)} . - * </b> - */ - @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") - @Deprecated - public static <E> ImmutableSortedMultiset<E> of(E e1, E e2, E e3, E e4, E e5) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code - * Comparable} element.</b> Proper calls will resolve to the version in {@code - * ImmutableSortedMultiset}, not this dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link - * ImmutableSortedMultiset#of(Comparable, Comparable, Comparable, Comparable, Comparable, - * Comparable, Comparable...)} . </b> - */ - @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") - @Deprecated - public static <E> ImmutableSortedMultiset<E> of( - E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a multiset that may contain non-{@code - * Comparable} elements.</b> Proper calls will resolve to the version in {@code - * ImmutableSortedMultiset}, not this dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass parameters of type {@code Comparable} to use {@link - * ImmutableSortedMultiset#copyOf(Comparable[])}.</b> - */ - @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)") - @Deprecated - public static <E> ImmutableSortedMultiset<E> copyOf(E[] elements) { - throw new UnsupportedOperationException(); - } - - /* - * We would like to include an unsupported "<E> copyOf(Iterable<E>)" here, providing only the - * properly typed "<E extends Comparable<E>> copyOf(Iterable<E>)" in ImmutableSortedMultiset (and - * likewise for the Iterator equivalent). However, due to a change in Sun's interpretation of the - * JLS (as described at http://bugs.sun.com/view_bug.do?bug_id=6182950), the OpenJDK 7 compiler - * available as of this writing rejects our attempts. To maintain compatibility with that version - * and with any other compilers that interpret the JLS similarly, there is no definition of - * copyOf() here, and the definition in ImmutableSortedMultiset matches that in - * ImmutableMultiset. - * - * The result is that ImmutableSortedMultiset.copyOf() may be called on non-Comparable elements. - * We have not discovered a better solution. In retrospect, the static factory methods should - * have gone in a separate class so that ImmutableSortedMultiset wouldn't "inherit" - * too-permissive factory methods from ImmutableMultiset. - */ -} diff --git a/guava/src/com/google/common/collect/ImmutableSortedSet.java b/guava/src/com/google/common/collect/ImmutableSortedSet.java index c730fa496..dc88e3983 100644 --- a/guava/src/com/google/common/collect/ImmutableSortedSet.java +++ b/guava/src/com/google/common/collect/ImmutableSortedSet.java @@ -64,7 +64,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; @GwtCompatible(serializable = true, emulated = true) @SuppressWarnings("serial") // we're overriding default serialization @ElementTypesAreNonnullByDefault -public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxverideShim<E> +public abstract class ImmutableSortedSet<E> extends ImmutableSet.CachingAsList<E> implements NavigableSet<E>, SortedIterable<E> { static final int SPLITERATOR_CHARACTERISTICS = ImmutableSet.SPLITERATOR_CHARACTERISTICS | Spliterator.SORTED; @@ -854,4 +854,153 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride Object writeReplace() { return new SerializedForm<E>(comparator, toArray()); } + + /** + * Not supported. Use {@link #toImmutableSortedSet} instead. This method exists only to hide + * {@link ImmutableSet#toImmutableSet} from consumers of {@code ImmutableSortedSet}. + * + * @throws UnsupportedOperationException always + * @deprecated Use {@link ImmutableSortedSet#toImmutableSortedSet}. + * @since 21.0 + */ + @DoNotCall("Use toImmutableSortedSet") + @Deprecated + public static <E> Collector<E, ?, ImmutableSet<E>> toImmutableSet() { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. Use {@link #naturalOrder}, which offers better type-safety, instead. This method + * exists only to hide {@link ImmutableSet#builder} from consumers of {@code ImmutableSortedSet}. + * + * @throws UnsupportedOperationException always + * @deprecated Use {@link ImmutableSortedSet#naturalOrder}, which offers better type-safety. + */ + @DoNotCall("Use naturalOrder") + @Deprecated + public static <E> ImmutableSortedSet.Builder<E> builder() { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. This method exists only to hide {@link ImmutableSet#builderWithExpectedSize} + * from consumers of {@code ImmutableSortedSet}. + * + * @throws UnsupportedOperationException always + * @deprecated Not supported by ImmutableSortedSet. + */ + @DoNotCall("Use naturalOrder (which does not accept an expected size)") + @Deprecated + public static <E> ImmutableSortedSet.Builder<E> builderWithExpectedSize(int expectedSize) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a set that may contain a non-{@code Comparable} + * element.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass a parameter of type {@code Comparable} to use {@link + * ImmutableSortedSet#of(Comparable)}.</b> + */ + @DoNotCall("Pass a parameter of type Comparable") + @Deprecated + public static <E> ImmutableSortedSet<E> of(E element) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a set that may contain a non-{@code Comparable} + * element.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link + * ImmutableSortedSet#of(Comparable, Comparable)}.</b> + */ + @DoNotCall("Pass parameters of type Comparable") + @Deprecated + public static <E> ImmutableSortedSet<E> of(E e1, E e2) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a set that may contain a non-{@code Comparable} + * element.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link + * ImmutableSortedSet#of(Comparable, Comparable, Comparable)}.</b> + */ + @DoNotCall("Pass parameters of type Comparable") + @Deprecated + public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a set that may contain a non-{@code Comparable} + * element.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link + * ImmutableSortedSet#of(Comparable, Comparable, Comparable, Comparable)}. </b> + */ + @DoNotCall("Pass parameters of type Comparable") + @Deprecated + public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a set that may contain a non-{@code Comparable} + * element.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link + * ImmutableSortedSet#of( Comparable, Comparable, Comparable, Comparable, Comparable)}. </b> + */ + @DoNotCall("Pass parameters of type Comparable") + @Deprecated + public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4, E e5) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a set that may contain a non-{@code Comparable} + * element.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link + * ImmutableSortedSet#of(Comparable, Comparable, Comparable, Comparable, Comparable, + * Comparable, Comparable...)}. </b> + */ + @DoNotCall("Pass parameters of type Comparable") + @Deprecated + public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. <b>You are attempting to create a set that may contain non-{@code Comparable} + * elements.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this + * dummy version. + * + * @throws UnsupportedOperationException always + * @deprecated <b>Pass parameters of type {@code Comparable} to use {@link + * ImmutableSortedSet#copyOf(Comparable[])}.</b> + */ + @DoNotCall("Pass parameters of type Comparable") + @Deprecated + // The usage of "Z" here works around bugs in Javadoc (JDK-8318093) and JDiff. + public static <Z> ImmutableSortedSet<Z> copyOf(Z[] elements) { + throw new UnsupportedOperationException(); + } + + private static final long serialVersionUID = 0xcafebabe; } diff --git a/guava/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java b/guava/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java deleted file mode 100644 index ff3ac12d5..000000000 --- a/guava/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2009 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.common.collect; - -import com.google.common.annotations.GwtIncompatible; -import com.google.errorprone.annotations.DoNotCall; -import java.util.stream.Collector; - -/** - * "Overrides" the {@link ImmutableSet} static methods that lack {@link ImmutableSortedSet} - * equivalents with deprecated, exception-throwing versions. This prevents accidents like the - * following: - * - * <pre>{@code - * List<Object> objects = ...; - * // Sort them: - * Set<Object> sorted = ImmutableSortedSet.copyOf(objects); - * // BAD CODE! The returned set is actually an unsorted ImmutableSet! - * }</pre> - * - * <p>While we could put the overrides in {@link ImmutableSortedSet} itself, it seems clearer to - * separate these "do not call" methods from those intended for normal use. - * - * @author Chris Povirk - */ -@GwtIncompatible -@ElementTypesAreNonnullByDefault -abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet.CachingAsList<E> { - /** - * Not supported. Use {@link ImmutableSortedSet#toImmutableSortedSet} instead. This method exists - * only to hide {@link ImmutableSet#toImmutableSet} from consumers of {@code ImmutableSortedSet}. - * - * @throws UnsupportedOperationException always - * @deprecated Use {@link ImmutableSortedSet#toImmutableSortedSet}. - * @since 21.0 - */ - @DoNotCall("Use toImmutableSortedSet") - @Deprecated - public static <E> Collector<E, ?, ImmutableSet<E>> toImmutableSet() { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. Use {@link ImmutableSortedSet#naturalOrder}, which offers better type-safety, - * instead. This method exists only to hide {@link ImmutableSet#builder} from consumers of {@code - * ImmutableSortedSet}. - * - * @throws UnsupportedOperationException always - * @deprecated Use {@link ImmutableSortedSet#naturalOrder}, which offers better type-safety. - */ - @DoNotCall("Use naturalOrder") - @Deprecated - public static <E> ImmutableSortedSet.Builder<E> builder() { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. This method exists only to hide {@link ImmutableSet#builderWithExpectedSize} - * from consumers of {@code ImmutableSortedSet}. - * - * @throws UnsupportedOperationException always - * @deprecated Not supported by ImmutableSortedSet. - */ - @DoNotCall("Use naturalOrder (which does not accept an expected size)") - @Deprecated - public static <E> ImmutableSortedSet.Builder<E> builderWithExpectedSize(int expectedSize) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a set that may contain a non-{@code Comparable} - * element.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass a parameter of type {@code Comparable} to use {@link - * ImmutableSortedSet#of(Comparable)}.</b> - */ - @DoNotCall("Pass a parameter of type Comparable") - @Deprecated - public static <E> ImmutableSortedSet<E> of(E element) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a set that may contain a non-{@code Comparable} - * element.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link - * ImmutableSortedSet#of(Comparable, Comparable)}.</b> - */ - @DoNotCall("Pass parameters of type Comparable") - @Deprecated - public static <E> ImmutableSortedSet<E> of(E e1, E e2) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a set that may contain a non-{@code Comparable} - * element.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link - * ImmutableSortedSet#of(Comparable, Comparable, Comparable)}.</b> - */ - @DoNotCall("Pass parameters of type Comparable") - @Deprecated - public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a set that may contain a non-{@code Comparable} - * element.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link - * ImmutableSortedSet#of(Comparable, Comparable, Comparable, Comparable)}. </b> - */ - @DoNotCall("Pass parameters of type Comparable") - @Deprecated - public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a set that may contain a non-{@code Comparable} - * element.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link - * ImmutableSortedSet#of( Comparable, Comparable, Comparable, Comparable, Comparable)}. </b> - */ - @DoNotCall("Pass parameters of type Comparable") - @Deprecated - public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4, E e5) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a set that may contain a non-{@code Comparable} - * element.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link - * ImmutableSortedSet#of(Comparable, Comparable, Comparable, Comparable, Comparable, - * Comparable, Comparable...)}. </b> - */ - @DoNotCall("Pass parameters of type Comparable") - @Deprecated - public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. <b>You are attempting to create a set that may contain non-{@code Comparable} - * elements.</b> Proper calls will resolve to the version in {@code ImmutableSortedSet}, not this - * dummy version. - * - * @throws UnsupportedOperationException always - * @deprecated <b>Pass parameters of type {@code Comparable} to use {@link - * ImmutableSortedSet#copyOf(Comparable[])}.</b> - */ - @DoNotCall("Pass parameters of type Comparable") - @Deprecated - public static <E> ImmutableSortedSet<E> copyOf(E[] elements) { - throw new UnsupportedOperationException(); - } - - /* - * We would like to include an unsupported "<E> copyOf(Iterable<E>)" here, - * providing only the properly typed - * "<E extends Comparable<E>> copyOf(Iterable<E>)" in ImmutableSortedSet (and - * likewise for the Iterator equivalent). However, due to a change in Sun's - * interpretation of the JLS (as described at - * http://bugs.sun.com/view_bug.do?bug_id=6182950), the OpenJDK 7 compiler - * available as of this writing rejects our attempts. To maintain - * compatibility with that version and with any other compilers that interpret - * the JLS similarly, there is no definition of copyOf() here, and the - * definition in ImmutableSortedSet matches that in ImmutableSet. - * - * The result is that ImmutableSortedSet.copyOf() may be called on - * non-Comparable elements. We have not discovered a better solution. In - * retrospect, the static factory methods should have gone in a separate class - * so that ImmutableSortedSet wouldn't "inherit" too-permissive factory - * methods from ImmutableSet. - */ -} diff --git a/guava/src/com/google/common/collect/ImmutableTable.java b/guava/src/com/google/common/collect/ImmutableTable.java index 62cae079f..e1db67c93 100644 --- a/guava/src/com/google/common/collect/ImmutableTable.java +++ b/guava/src/com/google/common/collect/ImmutableTable.java @@ -445,9 +445,6 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> throw new UnsupportedOperationException(); } - /** Creates the common serialized form for this table. */ - abstract SerializedForm createSerializedForm(); - /** * Serialized type for all ImmutableTable instances. It captures the logical contents and * preserves iteration order of all views. @@ -503,9 +500,9 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> private static final long serialVersionUID = 0; } - final Object writeReplace() { - return createSerializedForm(); - } + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + abstract Object writeReplace(); @GwtIncompatible // serialization @J2ktIncompatible diff --git a/guava/src/com/google/common/collect/IndexedImmutableSet.java b/guava/src/com/google/common/collect/IndexedImmutableSet.java index 20dfacbab..396ce6b0f 100644 --- a/guava/src/com/google/common/collect/IndexedImmutableSet.java +++ b/guava/src/com/google/common/collect/IndexedImmutableSet.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import java.util.Spliterator; import java.util.function.Consumer; import org.checkerframework.checker.nullness.qual.Nullable; @@ -76,6 +77,24 @@ abstract class IndexedImmutableSet<E> extends ImmutableSet.CachingAsList<E> { ImmutableCollection<E> delegateCollection() { return IndexedImmutableSet.this; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } }; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/Iterators.java b/guava/src/com/google/common/collect/Iterators.java index 0699202fe..009a41cef 100644 --- a/guava/src/com/google/common/collect/Iterators.java +++ b/guava/src/com/google/common/collect/Iterators.java @@ -42,7 +42,6 @@ import java.util.Deque; import java.util.Enumeration; import java.util.Iterator; import java.util.List; -import java.util.ListIterator; import java.util.NoSuchElementException; import java.util.PriorityQueue; import java.util.Queue; @@ -1056,47 +1055,40 @@ public final class Iterators { */ @SafeVarargs public static <T extends @Nullable Object> UnmodifiableIterator<T> forArray(T... array) { - return forArray(array, 0, array.length, 0); + return forArrayWithPosition(array, 0); } /** - * Returns a list iterator containing the elements in the specified range of {@code array} in - * order, starting at the specified index. + * Returns a list iterator containing the elements in the specified {@code array} in order, + * starting at the specified {@code position}. * * <p>The {@code Iterable} equivalent of this method is {@code - * Arrays.asList(array).subList(offset, offset + length).listIterator(index)}. + * Arrays.asList(array).listIterator(position)}. */ - static <T extends @Nullable Object> UnmodifiableListIterator<T> forArray( - T[] array, int offset, int length, int index) { - checkArgument(length >= 0); - int end = offset + length; - - // Technically we should give a slightly more descriptive error on overflow - Preconditions.checkPositionIndexes(offset, end, array.length); - Preconditions.checkPositionIndex(index, length); - if (length == 0) { + static <T extends @Nullable Object> UnmodifiableListIterator<T> forArrayWithPosition( + T[] array, int position) { + if (array.length == 0) { + Preconditions.checkPositionIndex(position, array.length); // otherwise checked in ArrayItr return emptyListIterator(); } - return new ArrayItr<>(array, offset, length, index); + return new ArrayItr<>(array, position); } private static final class ArrayItr<T extends @Nullable Object> extends AbstractIndexedListIterator<T> { - static final UnmodifiableListIterator<Object> EMPTY = new ArrayItr<>(new Object[0], 0, 0, 0); + static final UnmodifiableListIterator<Object> EMPTY = new ArrayItr<>(new Object[0], 0); private final T[] array; - private final int offset; - ArrayItr(T[] array, int offset, int length, int index) { - super(length, index); + ArrayItr(T[] array, int position) { + super(array.length, position); this.array = array; - this.offset = offset; } @Override @ParametricNullness protected T get(int index) { - return array[offset + index]; + return array[index]; } } @@ -1107,24 +1099,36 @@ public final class Iterators { */ public static <T extends @Nullable Object> UnmodifiableIterator<T> singletonIterator( @ParametricNullness T value) { - return new UnmodifiableIterator<T>() { - boolean done; + return new SingletonIterator<>(value); + } - @Override - public boolean hasNext() { - return !done; - } + private static final class SingletonIterator<T extends @Nullable Object> + extends UnmodifiableIterator<T> { + private static final Object SENTINEL = new Object(); - @Override - @ParametricNullness - public T next() { - if (done) { - throw new NoSuchElementException(); - } - done = true; - return value; + private Object valueOrSentinel; + + SingletonIterator(T value) { + this.valueOrSentinel = value; + } + + @Override + public boolean hasNext() { + return valueOrSentinel != SENTINEL; + } + + @Override + @ParametricNullness + public T next() { + if (valueOrSentinel == SENTINEL) { + throw new NoSuchElementException(); } - }; + // The field held either a T or SENTINEL, and it turned out not to be SENTINEL. + @SuppressWarnings("unchecked") + T t = (T) valueOrSentinel; + valueOrSentinel = SENTINEL; + return t; + } } /** @@ -1444,9 +1448,4 @@ public final class Iterators { toRemove = null; } } - - /** Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557 */ - static <T extends @Nullable Object> ListIterator<T> cast(Iterator<T> iterator) { - return (ListIterator<T>) iterator; - } } diff --git a/guava/src/com/google/common/collect/JdkBackedImmutableBiMap.java b/guava/src/com/google/common/collect/JdkBackedImmutableBiMap.java index f126fdea3..bf45138f7 100644 --- a/guava/src/com/google/common/collect/JdkBackedImmutableBiMap.java +++ b/guava/src/com/google/common/collect/JdkBackedImmutableBiMap.java @@ -18,6 +18,8 @@ package com.google.common.collect; import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.common.annotations.VisibleForTesting; import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.RetainedWith; @@ -102,6 +104,15 @@ final class JdkBackedImmutableBiMap<K, V> extends ImmutableBiMap<K, V> { public int size() { return entries.size(); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } @Override @@ -124,4 +135,13 @@ final class JdkBackedImmutableBiMap<K, V> extends ImmutableBiMap<K, V> { boolean isPartialView() { return false; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/JdkBackedImmutableMap.java b/guava/src/com/google/common/collect/JdkBackedImmutableMap.java index 222c4deb8..0dd791923 100644 --- a/guava/src/com/google/common/collect/JdkBackedImmutableMap.java +++ b/guava/src/com/google/common/collect/JdkBackedImmutableMap.java @@ -21,6 +21,8 @@ import static com.google.common.collect.RegularImmutableMap.makeImmutable; import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import java.util.HashMap; import java.util.Map; import java.util.function.BiConsumer; @@ -130,4 +132,13 @@ final class JdkBackedImmutableMap<K, V> extends ImmutableMap<K, V> { boolean isPartialView() { return false; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/JdkBackedImmutableMultiset.java b/guava/src/com/google/common/collect/JdkBackedImmutableMultiset.java index 41d95f045..8c116b351 100644 --- a/guava/src/com/google/common/collect/JdkBackedImmutableMultiset.java +++ b/guava/src/com/google/common/collect/JdkBackedImmutableMultiset.java @@ -17,6 +17,8 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.common.primitives.Ints; import com.google.errorprone.annotations.concurrent.LazyInit; import java.util.Collection; @@ -89,4 +91,13 @@ final class JdkBackedImmutableMultiset<E> extends ImmutableMultiset<E> { public int size() { return Ints.saturatedCast(size); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/JdkBackedImmutableSet.java b/guava/src/com/google/common/collect/JdkBackedImmutableSet.java index c00167713..bee7076fa 100644 --- a/guava/src/com/google/common/collect/JdkBackedImmutableSet.java +++ b/guava/src/com/google/common/collect/JdkBackedImmutableSet.java @@ -15,6 +15,8 @@ package com.google.common.collect; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import java.util.Set; import javax.annotation.CheckForNull; @@ -55,4 +57,13 @@ final class JdkBackedImmutableSet<E> extends IndexedImmutableSet<E> { public int size() { return delegateList.size(); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/LinkedHashMultimap.java b/guava/src/com/google/common/collect/LinkedHashMultimap.java index 78afd3268..61f2a0202 100644 --- a/guava/src/com/google/common/collect/LinkedHashMultimap.java +++ b/guava/src/com/google/common/collect/LinkedHashMultimap.java @@ -193,11 +193,11 @@ public final class LinkedHashMultimap<K extends @Nullable Object, V extends @Nul * frameworks like Android that define post-construct hooks like Activity.onCreate, etc. */ - @CheckForNull ValueSetLink<K, V> predecessorInValueSet; - @CheckForNull ValueSetLink<K, V> successorInValueSet; + @CheckForNull private ValueSetLink<K, V> predecessorInValueSet; + @CheckForNull private ValueSetLink<K, V> successorInValueSet; - @CheckForNull ValueEntry<K, V> predecessorInMultimap; - @CheckForNull ValueEntry<K, V> successorInMultimap; + @CheckForNull private ValueEntry<K, V> predecessorInMultimap; + @CheckForNull private ValueEntry<K, V> successorInMultimap; ValueEntry( @ParametricNullness K key, diff --git a/guava/src/com/google/common/collect/LinkedListMultimap.java b/guava/src/com/google/common/collect/LinkedListMultimap.java index d88564ca5..d5edcb8ce 100644 --- a/guava/src/com/google/common/collect/LinkedListMultimap.java +++ b/guava/src/com/google/common/collect/LinkedListMultimap.java @@ -107,7 +107,7 @@ public class LinkedListMultimap<K extends @Nullable Object, V extends @Nullable * ValueForKeyIterator} in constant time. */ - private static final class Node<K extends @Nullable Object, V extends @Nullable Object> + static final class Node<K extends @Nullable Object, V extends @Nullable Object> extends AbstractMapEntry<K, V> { @ParametricNullness final K key; @ParametricNullness V value; diff --git a/guava/src/com/google/common/collect/Lists.java b/guava/src/com/google/common/collect/Lists.java index 0816b754a..a9c99e27a 100644 --- a/guava/src/com/google/common/collect/Lists.java +++ b/guava/src/com/google/common/collect/Lists.java @@ -780,6 +780,15 @@ public final class Lists { public int size() { return string.length(); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } private static final class CharSequenceAsList extends AbstractList<Character> { diff --git a/guava/src/com/google/common/collect/Maps.java b/guava/src/com/google/common/collect/Maps.java index 173447caf..9bc33913e 100644 --- a/guava/src/com/google/common/collect/Maps.java +++ b/guava/src/com/google/common/collect/Maps.java @@ -1737,22 +1737,33 @@ public final class Maps { throw new UnsupportedOperationException(); } + /* + * TODO(cpovirk): Uncomment the @NonNull annotations below once our JDK stubs and J2KT + * emulations include them. + */ @Override + @CheckForNull public V computeIfPresent( - K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + K key, + BiFunction<? super K, ? super /*@NonNull*/ V, ? extends @Nullable V> remappingFunction) { throw new UnsupportedOperationException(); } @Override + @CheckForNull public V compute( - K key, BiFunction<? super K, ? super @Nullable V, ? extends V> remappingFunction) { + K key, + BiFunction<? super K, ? super @Nullable V, ? extends @Nullable V> remappingFunction) { throw new UnsupportedOperationException(); } @Override @CheckForNull public V merge( - K key, V value, BiFunction<? super V, ? super V, ? extends @Nullable V> function) { + K key, + /*@NonNull*/ V value, + BiFunction<? super /*@NonNull*/ V, ? super /*@NonNull*/ V, ? extends @Nullable V> + function) { throw new UnsupportedOperationException(); } @@ -3644,22 +3655,33 @@ public final class Maps { throw new UnsupportedOperationException(); } + /* + * TODO(cpovirk): Uncomment the @NonNull annotations below once our JDK stubs and J2KT + * emulations include them. + */ @Override + @CheckForNull public V computeIfPresent( - K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + K key, + BiFunction<? super K, ? super /*@NonNull*/ V, ? extends @Nullable V> remappingFunction) { throw new UnsupportedOperationException(); } @Override + @CheckForNull public V compute( - K key, BiFunction<? super K, ? super @Nullable V, ? extends V> remappingFunction) { + K key, + BiFunction<? super K, ? super @Nullable V, ? extends @Nullable V> remappingFunction) { throw new UnsupportedOperationException(); } @Override @CheckForNull public V merge( - K key, V value, BiFunction<? super V, ? super V, ? extends @Nullable V> function) { + K key, + /*@NonNull*/ V value, + BiFunction<? super /*@NonNull*/ V, ? super /*@NonNull*/ V, ? extends @Nullable V> + function) { throw new UnsupportedOperationException(); } diff --git a/guava/src/com/google/common/collect/MinMaxPriorityQueue.java b/guava/src/com/google/common/collect/MinMaxPriorityQueue.java index 877d6bc0b..0dfa2b2fc 100644 --- a/guava/src/com/google/common/collect/MinMaxPriorityQueue.java +++ b/guava/src/com/google/common/collect/MinMaxPriorityQueue.java @@ -521,7 +521,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> { * sake they are stored interleaved on alternate heap levels in the same array (MMPQ.queue). */ @WeakOuter - private class Heap { + class Heap { final Ordering<E> ordering; @SuppressWarnings("nullness:initialization.field.uninitialized") diff --git a/guava/src/com/google/common/collect/Multimaps.java b/guava/src/com/google/common/collect/Multimaps.java index c614764c5..c158c6519 100644 --- a/guava/src/com/google/common/collect/Multimaps.java +++ b/guava/src/com/google/common/collect/Multimaps.java @@ -122,7 +122,7 @@ public final class Multimaps { java.util.function.Function<? super T, ? extends K> keyFunction, java.util.function.Function<? super T, ? extends V> valueFunction, java.util.function.Supplier<M> multimapSupplier) { - return CollectCollectors.toMultimap(keyFunction, valueFunction, multimapSupplier); + return CollectCollectors.<T, K, V, M>toMultimap(keyFunction, valueFunction, multimapSupplier); } /** @@ -167,7 +167,8 @@ public final class Multimaps { java.util.function.Function<? super T, ? extends K> keyFunction, java.util.function.Function<? super T, ? extends Stream<? extends V>> valueFunction, java.util.function.Supplier<M> multimapSupplier) { - return CollectCollectors.flatteningToMultimap(keyFunction, valueFunction, multimapSupplier); + return CollectCollectors.<T, K, V, M>flatteningToMultimap( + keyFunction, valueFunction, multimapSupplier); } /** @@ -285,8 +286,8 @@ public final class Multimaps { @SuppressWarnings("unchecked") // reading data stored by writeObject private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); - factory = (Supplier<? extends Collection<V>>) stream.readObject(); - Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject(); + factory = (Supplier<? extends Collection<V>>) requireNonNull(stream.readObject()); + Map<K, Collection<V>> map = (Map<K, Collection<V>>) requireNonNull(stream.readObject()); setMap(map); } @@ -371,8 +372,8 @@ public final class Multimaps { @SuppressWarnings("unchecked") // reading data stored by writeObject private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); - factory = (Supplier<? extends List<V>>) stream.readObject(); - Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject(); + factory = (Supplier<? extends List<V>>) requireNonNull(stream.readObject()); + Map<K, Collection<V>> map = (Map<K, Collection<V>>) requireNonNull(stream.readObject()); setMap(map); } @@ -479,8 +480,8 @@ public final class Multimaps { @SuppressWarnings("unchecked") // reading data stored by writeObject private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); - factory = (Supplier<? extends Set<V>>) stream.readObject(); - Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject(); + factory = (Supplier<? extends Set<V>>) requireNonNull(stream.readObject()); + Map<K, Collection<V>> map = (Map<K, Collection<V>>) requireNonNull(stream.readObject()); setMap(map); } @@ -573,9 +574,9 @@ public final class Multimaps { @SuppressWarnings("unchecked") // reading data stored by writeObject private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); - factory = (Supplier<? extends SortedSet<V>>) stream.readObject(); + factory = (Supplier<? extends SortedSet<V>>) requireNonNull(stream.readObject()); valueComparator = factory.get().comparator(); - Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject(); + Map<K, Collection<V>> map = (Map<K, Collection<V>>) requireNonNull(stream.readObject()); setMap(map); } diff --git a/guava/src/com/google/common/collect/Multisets.java b/guava/src/com/google/common/collect/Multisets.java index fcc674472..7a0eb10a3 100644 --- a/guava/src/com/google/common/collect/Multisets.java +++ b/guava/src/com/google/common/collect/Multisets.java @@ -196,6 +196,11 @@ public final class Multisets { } @Override + public boolean removeIf(java.util.function.Predicate<? super E> filter) { + throw new UnsupportedOperationException(); + } + + @Override public boolean retainAll(Collection<?> elementsToRetain) { throw new UnsupportedOperationException(); } @@ -1166,7 +1171,7 @@ public final class Multisets { } private static final class DecreasingCount implements Comparator<Entry<?>> { - static final DecreasingCount INSTANCE = new DecreasingCount(); + static final Comparator<Entry<?>> INSTANCE = new DecreasingCount(); @Override public int compare(Entry<?> entry1, Entry<?> entry2) { diff --git a/guava/src/com/google/common/collect/Platform.java b/guava/src/com/google/common/collect/Platform.java index 3f118764e..7ae061c83 100644 --- a/guava/src/com/google/common/collect/Platform.java +++ b/guava/src/com/google/common/collect/Platform.java @@ -32,8 +32,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; @GwtCompatible(emulated = true) @ElementTypesAreNonnullByDefault final class Platform { - private static final java.util.logging.Logger logger = - java.util.logging.Logger.getLogger(Platform.class.getName()); /** Returns the platform preferred implementation of a map based on a hash table. */ static <K extends @Nullable Object, V extends @Nullable Object> @@ -82,7 +80,7 @@ final class Platform { * for insertions. */ static <E extends @Nullable Object> Set<E> preservesInsertionOrderOnAddsSet() { - return Sets.newLinkedHashSet(); + return CompactHashSet.create(); } /** diff --git a/guava/src/com/google/common/collect/RegularContiguousSet.java b/guava/src/com/google/common/collect/RegularContiguousSet.java index 9c2e5a26f..8159d107b 100644 --- a/guava/src/com/google/common/collect/RegularContiguousSet.java +++ b/guava/src/com/google/common/collect/RegularContiguousSet.java @@ -143,6 +143,15 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C> checkElementIndex(i, size()); return domain.offset(first(), i); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } }; } else { return super.createAsList(); diff --git a/guava/src/com/google/common/collect/RegularImmutableAsList.java b/guava/src/com/google/common/collect/RegularImmutableAsList.java index 0e3fe4ec8..bc4d8ae5d 100644 --- a/guava/src/com/google/common/collect/RegularImmutableAsList.java +++ b/guava/src/com/google/common/collect/RegularImmutableAsList.java @@ -18,6 +18,7 @@ package com.google.common.collect; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import java.util.function.Consumer; import javax.annotation.CheckForNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -91,4 +92,13 @@ class RegularImmutableAsList<E> extends ImmutableAsList<E> { public E get(int index) { return delegateList.get(index); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/RegularImmutableBiMap.java b/guava/src/com/google/common/collect/RegularImmutableBiMap.java index 333b80177..e97a86934 100644 --- a/guava/src/com/google/common/collect/RegularImmutableBiMap.java +++ b/guava/src/com/google/common/collect/RegularImmutableBiMap.java @@ -25,6 +25,7 @@ import static com.google.common.collect.RegularImmutableMap.checkNoConflictInKey import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMapEntry.NonTerminalImmutableBiMapEntry; @@ -285,8 +286,26 @@ class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> { ImmutableCollection<Entry<V, K>> delegateCollection() { return InverseEntrySet.this; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } }; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } @Override @@ -296,6 +315,7 @@ class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> { @Override @J2ktIncompatible // serialization + @GwtIncompatible // serialization Object writeReplace() { return new InverseSerializedForm<>(RegularImmutableBiMap.this); } @@ -320,4 +340,13 @@ class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> { private static final long serialVersionUID = 1; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/RegularImmutableList.java b/guava/src/com/google/common/collect/RegularImmutableList.java index 397147d70..915c6e2c7 100644 --- a/guava/src/com/google/common/collect/RegularImmutableList.java +++ b/guava/src/com/google/common/collect/RegularImmutableList.java @@ -17,6 +17,8 @@ package com.google.common.collect; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.common.annotations.VisibleForTesting; import java.util.Spliterator; import java.util.Spliterators; @@ -82,7 +84,7 @@ class RegularImmutableList<E> extends ImmutableList<E> { public UnmodifiableListIterator<E> listIterator(int index) { // for performance // The fake cast to E is safe because the creation methods only allow E's - return (UnmodifiableListIterator<E>) Iterators.forArray(array, 0, array.length, index); + return (UnmodifiableListIterator<E>) Iterators.forArrayWithPosition(array, index); } @Override @@ -91,4 +93,13 @@ class RegularImmutableList<E> extends ImmutableList<E> { } // TODO(lowasser): benchmark optimizations for equals() and see if they're worthwhile + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/RegularImmutableMap.java b/guava/src/com/google/common/collect/RegularImmutableMap.java index 42649109a..32aa2507a 100644 --- a/guava/src/com/google/common/collect/RegularImmutableMap.java +++ b/guava/src/com/google/common/collect/RegularImmutableMap.java @@ -346,6 +346,15 @@ final class RegularImmutableMap<K, V> extends ImmutableMap<K, V> { return map.size(); } + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } + // No longer used for new writes, but kept so that old data can still be read. @GwtIncompatible // serialization @J2ktIncompatible @@ -394,6 +403,15 @@ final class RegularImmutableMap<K, V> extends ImmutableMap<K, V> { return true; } + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } + // No longer used for new writes, but kept so that old data can still be read. @GwtIncompatible // serialization @J2ktIncompatible @@ -414,6 +432,15 @@ final class RegularImmutableMap<K, V> extends ImmutableMap<K, V> { } } + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } + // This class is never actually serialized directly, but we have to make the // warning go away (and suppressing would suppress for all nested classes too) @J2ktIncompatible // serialization diff --git a/guava/src/com/google/common/collect/RegularImmutableMultiset.java b/guava/src/com/google/common/collect/RegularImmutableMultiset.java index 026919e0d..8b50345b3 100644 --- a/guava/src/com/google/common/collect/RegularImmutableMultiset.java +++ b/guava/src/com/google/common/collect/RegularImmutableMultiset.java @@ -17,6 +17,8 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; import com.google.common.collect.Multisets.ImmutableEntry; @@ -194,4 +196,13 @@ class RegularImmutableMultiset<E> extends ImmutableMultiset<E> { public int hashCode() { return hashCode; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/RegularImmutableSet.java b/guava/src/com/google/common/collect/RegularImmutableSet.java index 211c89304..0db235d69 100644 --- a/guava/src/com/google/common/collect/RegularImmutableSet.java +++ b/guava/src/com/google/common/collect/RegularImmutableSet.java @@ -17,6 +17,8 @@ package com.google.common.collect; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.common.annotations.VisibleForTesting; import java.util.Spliterator; import java.util.Spliterators; @@ -124,4 +126,13 @@ final class RegularImmutableSet<E> extends ImmutableSet.CachingAsList<E> { boolean isHashCodeFast() { return true; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java b/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java index 4b7ba8742..258f7aa09 100644 --- a/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java +++ b/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java @@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkPositionIndexes; import static com.google.common.collect.BoundType.CLOSED; import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.common.annotations.VisibleForTesting; import com.google.common.primitives.Ints; import java.util.Comparator; @@ -133,4 +134,12 @@ final class RegularImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E> boolean isPartialView() { return offset > 0 || length < cumulativeCounts.length - 1; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/RegularImmutableSortedSet.java b/guava/src/com/google/common/collect/RegularImmutableSortedSet.java index 572e0acbf..970e85112 100644 --- a/guava/src/com/google/common/collect/RegularImmutableSortedSet.java +++ b/guava/src/com/google/common/collect/RegularImmutableSortedSet.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -329,4 +330,13 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> { ? emptySet(reversedOrder) : new RegularImmutableSortedSet<E>(elements.reverse(), reversedOrder); } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/RegularImmutableTable.java b/guava/src/com/google/common/collect/RegularImmutableTable.java index 337f123b6..03def2cbc 100644 --- a/guava/src/com/google/common/collect/RegularImmutableTable.java +++ b/guava/src/com/google/common/collect/RegularImmutableTable.java @@ -18,6 +18,8 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.j2objc.annotations.WeakOuter; import java.util.Collections; import java.util.Comparator; @@ -69,6 +71,15 @@ abstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> { boolean isPartialView() { return false; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } abstract V getValue(int iterationIndex); @@ -94,6 +105,15 @@ abstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> { boolean isPartialView() { return true; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } static <R, C, V> RegularImmutableTable<R, C, V> forCells( @@ -181,4 +201,10 @@ abstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> { newValue, existingValue); } + + // redeclare to satisfy our test for b/310253115 + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + abstract Object writeReplace(); } diff --git a/guava/src/com/google/common/collect/Sets.java b/guava/src/com/google/common/collect/Sets.java index da3814881..c38181001 100644 --- a/guava/src/com/google/common/collect/Sets.java +++ b/guava/src/com/google/common/collect/Sets.java @@ -1432,6 +1432,15 @@ public final class Sets { boolean isPartialView() { return true; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } }; return new CartesianSet<E>(axes, new CartesianList<E>(listAxes)); } @@ -1473,7 +1482,11 @@ public final class Sets { CartesianSet<?> that = (CartesianSet<?>) object; return this.axes.equals(that.axes); } - return super.equals(object); + if (object instanceof Set) { + Set<?> that = (Set<?>) object; + return this.size() == that.size() && this.containsAll(that); + } + return false; } @Override diff --git a/guava/src/com/google/common/collect/SingletonImmutableBiMap.java b/guava/src/com/google/common/collect/SingletonImmutableBiMap.java index c5fb2b298..c2f4ae137 100644 --- a/guava/src/com/google/common/collect/SingletonImmutableBiMap.java +++ b/guava/src/com/google/common/collect/SingletonImmutableBiMap.java @@ -20,6 +20,8 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.CollectPreconditions.checkEntryNotNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.RetainedWith; import java.util.function.BiConsumer; @@ -110,4 +112,13 @@ final class SingletonImmutableBiMap<K, V> extends ImmutableBiMap<K, V> { } } } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/SingletonImmutableList.java b/guava/src/com/google/common/collect/SingletonImmutableList.java index a7ac8b30e..ba1b1a713 100644 --- a/guava/src/com/google/common/collect/SingletonImmutableList.java +++ b/guava/src/com/google/common/collect/SingletonImmutableList.java @@ -19,6 +19,8 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.common.base.Preconditions; import java.util.Collections; import java.util.Spliterator; @@ -75,4 +77,13 @@ final class SingletonImmutableList<E> extends ImmutableList<E> { boolean isPartialView() { return false; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/SingletonImmutableSet.java b/guava/src/com/google/common/collect/SingletonImmutableSet.java index 088cb802f..15db1c5e5 100644 --- a/guava/src/com/google/common/collect/SingletonImmutableSet.java +++ b/guava/src/com/google/common/collect/SingletonImmutableSet.java @@ -17,6 +17,8 @@ package com.google.common.collect; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.common.base.Preconditions; import javax.annotation.CheckForNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -80,4 +82,13 @@ final class SingletonImmutableSet<E> extends ImmutableSet<E> { public String toString() { return '[' + element.toString() + ']'; } + + // redeclare to help optimizers with b/310253115 + @SuppressWarnings("RedundantOverride") + @Override + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { + return super.writeReplace(); + } } diff --git a/guava/src/com/google/common/collect/SingletonImmutableTable.java b/guava/src/com/google/common/collect/SingletonImmutableTable.java index cfaeadb41..6f839ceb4 100644 --- a/guava/src/com/google/common/collect/SingletonImmutableTable.java +++ b/guava/src/com/google/common/collect/SingletonImmutableTable.java @@ -19,6 +19,8 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import java.util.Map; /** @@ -77,7 +79,9 @@ class SingletonImmutableTable<R, C, V> extends ImmutableTable<R, C, V> { } @Override - SerializedForm createSerializedForm() { + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { return SerializedForm.create(this, new int[] {0}, new int[] {0}); } } diff --git a/guava/src/com/google/common/collect/SparseImmutableTable.java b/guava/src/com/google/common/collect/SparseImmutableTable.java index 44881fde7..f7222b120 100644 --- a/guava/src/com/google/common/collect/SparseImmutableTable.java +++ b/guava/src/com/google/common/collect/SparseImmutableTable.java @@ -17,6 +17,8 @@ package com.google.common.collect; import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.J2ktIncompatible; import com.google.errorprone.annotations.Immutable; import java.util.LinkedHashMap; import java.util.Map; @@ -130,7 +132,9 @@ final class SparseImmutableTable<R, C, V> extends RegularImmutableTable<R, C, V> } @Override - SerializedForm createSerializedForm() { + @J2ktIncompatible // serialization + @GwtIncompatible // serialization + Object writeReplace() { Map<C, Integer> columnKeyToIndex = Maps.indexMap(columnKeySet()); int[] cellColumnIndices = new int[cellSet().size()]; int i = 0; diff --git a/guava/src/com/google/common/collect/StandardTable.java b/guava/src/com/google/common/collect/StandardTable.java index 6ec3c6b23..f9d6f1b8e 100644 --- a/guava/src/com/google/common/collect/StandardTable.java +++ b/guava/src/com/google/common/collect/StandardTable.java @@ -846,7 +846,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa } @WeakOuter - class EntrySet extends TableSet<Entry<R, Map<C, V>>> { + private final class EntrySet extends TableSet<Entry<R, Map<C, V>>> { @Override public Iterator<Entry<R, Map<C, V>>> iterator() { return Maps.asMapEntryIterator( @@ -935,7 +935,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa } @WeakOuter - class ColumnMapEntrySet extends TableSet<Entry<C, Map<R, V>>> { + private final class ColumnMapEntrySet extends TableSet<Entry<C, Map<R, V>>> { @Override public Iterator<Entry<C, Map<R, V>>> iterator() { return Maps.asMapEntryIterator( diff --git a/guava/src/com/google/common/collect/Streams.java b/guava/src/com/google/common/collect/Streams.java index 0b6e88ce2..8209cedb5 100644 --- a/guava/src/com/google/common/collect/Streams.java +++ b/guava/src/com/google/common/collect/Streams.java @@ -148,11 +148,40 @@ public final class Streams { return optional.isPresent() ? DoubleStream.of(optional.getAsDouble()) : DoubleStream.empty(); } + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception private static void closeAll(BaseStream<?, ?>[] toClose) { + // If one of the streams throws an exception, continue closing the others, then throw the + // exception later. If more than one stream throws an exception, the later ones are added to the + // first as suppressed exceptions. We don't catch Error on the grounds that it should be allowed + // to propagate immediately. + Exception exception = null; for (BaseStream<?, ?> stream : toClose) { - // TODO(b/80534298): Catch exceptions, rethrowing later with extras as suppressed exceptions. - stream.close(); + try { + stream.close(); + } catch (Exception e) { // sneaky checked exception + if (exception == null) { + exception = e; + } else { + exception.addSuppressed(e); + } + } + } + if (exception != null) { + // Normally this is a RuntimeException that doesn't need sneakyThrow. + // But theoretically we could see sneaky checked exception + sneakyThrow(exception); + } + } + + /** Throws an undeclared checked exception. */ + private static void sneakyThrow(Throwable t) { + class SneakyThrower<T extends Throwable> { + @SuppressWarnings("unchecked") // not really safe, but that's the point + void throwIt(Throwable t) throws T { + throw (T) t; + } } + new SneakyThrower<Error>().throwIt(t); } /** diff --git a/guava/src/com/google/common/collect/Synchronized.java b/guava/src/com/google/common/collect/Synchronized.java index b1422e316..89916cd4d 100644 --- a/guava/src/com/google/common/collect/Synchronized.java +++ b/guava/src/com/google/common/collect/Synchronized.java @@ -369,8 +369,8 @@ final class Synchronized { : new SynchronizedList<E>(list, mutex); } - private static class SynchronizedList<E extends @Nullable Object> - extends SynchronizedCollection<E> implements List<E> { + static class SynchronizedList<E extends @Nullable Object> extends SynchronizedCollection<E> + implements List<E> { SynchronizedList(List<E> delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @@ -480,7 +480,7 @@ final class Synchronized { private static final long serialVersionUID = 0; } - private static class SynchronizedRandomAccessList<E extends @Nullable Object> + static final class SynchronizedRandomAccessList<E extends @Nullable Object> extends SynchronizedList<E> implements RandomAccess { SynchronizedRandomAccessList(List<E> list, @CheckForNull Object mutex) { super(list, mutex); @@ -497,7 +497,7 @@ final class Synchronized { return new SynchronizedMultiset<E>(multiset, mutex); } - private static class SynchronizedMultiset<E extends @Nullable Object> + static final class SynchronizedMultiset<E extends @Nullable Object> extends SynchronizedCollection<E> implements Multiset<E> { @CheckForNull transient Set<E> elementSet; @CheckForNull transient Set<Multiset.Entry<E>> entrySet; @@ -594,7 +594,7 @@ final class Synchronized { return new SynchronizedMultimap<>(multimap, mutex); } - private static class SynchronizedMultimap<K extends @Nullable Object, V extends @Nullable Object> + static class SynchronizedMultimap<K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedObject implements Multimap<K, V> { @CheckForNull transient Set<K> keySet; @CheckForNull transient Collection<V> valuesCollection; @@ -788,7 +788,7 @@ final class Synchronized { return new SynchronizedListMultimap<>(multimap, mutex); } - private static class SynchronizedListMultimap< + static final class SynchronizedListMultimap< K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedMultimap<K, V> implements ListMultimap<K, V> { SynchronizedListMultimap(ListMultimap<K, V> delegate, @CheckForNull Object mutex) { @@ -832,8 +832,7 @@ final class Synchronized { return new SynchronizedSetMultimap<>(multimap, mutex); } - private static class SynchronizedSetMultimap< - K extends @Nullable Object, V extends @Nullable Object> + static class SynchronizedSetMultimap<K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedMultimap<K, V> implements SetMultimap<K, V> { @CheckForNull transient Set<Map.Entry<K, V>> entrySet; @@ -889,7 +888,7 @@ final class Synchronized { return new SynchronizedSortedSetMultimap<>(multimap, mutex); } - private static class SynchronizedSortedSetMultimap< + static final class SynchronizedSortedSetMultimap< K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedSetMultimap<K, V> implements SortedSetMultimap<K, V> { SynchronizedSortedSetMultimap(SortedSetMultimap<K, V> delegate, @CheckForNull Object mutex) { @@ -956,7 +955,7 @@ final class Synchronized { } } - private static class SynchronizedAsMapEntries< + static final class SynchronizedAsMapEntries< K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedSet<Map.Entry<K, Collection<V>>> { SynchronizedAsMapEntries( @@ -1063,7 +1062,7 @@ final class Synchronized { return new SynchronizedMap<>(map, mutex); } - private static class SynchronizedMap<K extends @Nullable Object, V extends @Nullable Object> + static class SynchronizedMap<K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedObject implements Map<K, V> { @CheckForNull transient Set<K> keySet; @CheckForNull transient Collection<V> values; @@ -1188,17 +1187,25 @@ final class Synchronized { } } + /* + * TODO(cpovirk): Uncomment the @NonNull annotations below once our JDK stubs and J2KT + * emulations include them. + */ @Override + @CheckForNull public V computeIfPresent( - K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + K key, + BiFunction<? super K, ? super /*@NonNull*/ V, ? extends @Nullable V> remappingFunction) { synchronized (mutex) { return delegate().computeIfPresent(key, remappingFunction); } } @Override + @CheckForNull public V compute( - K key, BiFunction<? super K, ? super @Nullable V, ? extends V> remappingFunction) { + K key, + BiFunction<? super K, ? super @Nullable V, ? extends @Nullable V> remappingFunction) { synchronized (mutex) { return delegate().compute(key, remappingFunction); } @@ -1207,7 +1214,10 @@ final class Synchronized { @Override @CheckForNull public V merge( - K key, V value, BiFunction<? super V, ? super V, ? extends @Nullable V> remappingFunction) { + K key, + /*@NonNull*/ V value, + BiFunction<? super /*@NonNull*/ V, ? super /*@NonNull*/ V, ? extends @Nullable V> + remappingFunction) { synchronized (mutex) { return delegate().merge(key, value, remappingFunction); } @@ -1350,8 +1360,7 @@ final class Synchronized { return new SynchronizedBiMap<>(bimap, mutex, null); } - @VisibleForTesting - static class SynchronizedBiMap<K extends @Nullable Object, V extends @Nullable Object> + static final class SynchronizedBiMap<K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedMap<K, V> implements BiMap<K, V>, Serializable { @CheckForNull private transient Set<V> valueSet; @RetainedWith @CheckForNull private transient BiMap<V, K> inverse; @@ -1398,7 +1407,7 @@ final class Synchronized { private static final long serialVersionUID = 0; } - private static class SynchronizedAsMap<K extends @Nullable Object, V extends @Nullable Object> + static final class SynchronizedAsMap<K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedMap<K, Collection<V>> { @CheckForNull transient Set<Map.Entry<K, Collection<V>>> asMapEntrySet; @CheckForNull transient Collection<Collection<V>> asMapValues; @@ -1445,7 +1454,7 @@ final class Synchronized { private static final long serialVersionUID = 0; } - private static class SynchronizedAsMapValues<V extends @Nullable Object> + static final class SynchronizedAsMapValues<V extends @Nullable Object> extends SynchronizedCollection<Collection<V>> { SynchronizedAsMapValues(Collection<Collection<V>> delegate, @CheckForNull Object mutex) { super(delegate, mutex); @@ -1467,8 +1476,8 @@ final class Synchronized { @GwtIncompatible // NavigableSet @VisibleForTesting - static class SynchronizedNavigableSet<E extends @Nullable Object> extends SynchronizedSortedSet<E> - implements NavigableSet<E> { + static final class SynchronizedNavigableSet<E extends @Nullable Object> + extends SynchronizedSortedSet<E> implements NavigableSet<E> { SynchronizedNavigableSet(NavigableSet<E> delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @@ -1611,7 +1620,8 @@ final class Synchronized { @GwtIncompatible // NavigableMap @VisibleForTesting - static class SynchronizedNavigableMap<K extends @Nullable Object, V extends @Nullable Object> + static final class SynchronizedNavigableMap< + K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedSortedMap<K, V> implements NavigableMap<K, V> { SynchronizedNavigableMap(NavigableMap<K, V> delegate, @CheckForNull Object mutex) { @@ -1812,7 +1822,7 @@ final class Synchronized { } @GwtIncompatible // works but is needed only for NavigableMap - private static class SynchronizedEntry<K extends @Nullable Object, V extends @Nullable Object> + static final class SynchronizedEntry<K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedObject implements Map.Entry<K, V> { SynchronizedEntry(Map.Entry<K, V> delegate, @CheckForNull Object mutex) { @@ -1867,8 +1877,8 @@ final class Synchronized { return (queue instanceof SynchronizedQueue) ? queue : new SynchronizedQueue<E>(queue, mutex); } - private static class SynchronizedQueue<E extends @Nullable Object> - extends SynchronizedCollection<E> implements Queue<E> { + static class SynchronizedQueue<E extends @Nullable Object> extends SynchronizedCollection<E> + implements Queue<E> { SynchronizedQueue(Queue<E> delegate, @CheckForNull Object mutex) { super(delegate, mutex); @@ -1923,8 +1933,8 @@ final class Synchronized { return new SynchronizedDeque<E>(deque, mutex); } - private static final class SynchronizedDeque<E extends @Nullable Object> - extends SynchronizedQueue<E> implements Deque<E> { + static final class SynchronizedDeque<E extends @Nullable Object> extends SynchronizedQueue<E> + implements Deque<E> { SynchronizedDeque(Deque<E> delegate, @CheckForNull Object mutex) { super(delegate, mutex); @@ -2066,7 +2076,7 @@ final class Synchronized { return new SynchronizedTable<>(table, mutex); } - private static final class SynchronizedTable< + static final class SynchronizedTable< R extends @Nullable Object, C extends @Nullable Object, V extends @Nullable Object> extends SynchronizedObject implements Table<R, C, V> { diff --git a/guava/src/com/google/common/collect/TableCollectors.java b/guava/src/com/google/common/collect/TableCollectors.java index 16fcb1669..0257954ee 100644 --- a/guava/src/com/google/common/collect/TableCollectors.java +++ b/guava/src/com/google/common/collect/TableCollectors.java @@ -90,7 +90,7 @@ final class TableCollectors { java.util.function.Function<? super T, ? extends C> columnFunction, java.util.function.Function<? super T, ? extends V> valueFunction, java.util.function.Supplier<I> tableSupplier) { - return toTable( + return TableCollectors.<T, R, C, V, I>toTable( rowFunction, columnFunction, valueFunction, diff --git a/guava/src/com/google/common/collect/Tables.java b/guava/src/com/google/common/collect/Tables.java index 525c05355..a9d0bb654 100644 --- a/guava/src/com/google/common/collect/Tables.java +++ b/guava/src/com/google/common/collect/Tables.java @@ -77,7 +77,8 @@ public final class Tables { java.util.function.Function<? super T, ? extends C> columnFunction, java.util.function.Function<? super T, ? extends V> valueFunction, java.util.function.Supplier<I> tableSupplier) { - return TableCollectors.toTable(rowFunction, columnFunction, valueFunction, tableSupplier); + return TableCollectors.<T, R, C, V, I>toTable( + rowFunction, columnFunction, valueFunction, tableSupplier); } /** @@ -106,7 +107,7 @@ public final class Tables { java.util.function.Function<? super T, ? extends V> valueFunction, BinaryOperator<V> mergeFunction, java.util.function.Supplier<I> tableSupplier) { - return TableCollectors.toTable( + return TableCollectors.<T, R, C, V, I>toTable( rowFunction, columnFunction, valueFunction, mergeFunction, tableSupplier); } @@ -674,7 +675,7 @@ public final class Tables { return new UnmodifiableRowSortedMap<>(table); } - static final class UnmodifiableRowSortedMap< + private static final class UnmodifiableRowSortedMap< R extends @Nullable Object, C extends @Nullable Object, V extends @Nullable Object> extends UnmodifiableTable<R, C, V> implements RowSortedTable<R, C, V> { diff --git a/guava/src/com/google/common/collect/TransformedListIterator.java b/guava/src/com/google/common/collect/TransformedListIterator.java index 66b42e4c6..22b4b7c42 100644 --- a/guava/src/com/google/common/collect/TransformedListIterator.java +++ b/guava/src/com/google/common/collect/TransformedListIterator.java @@ -36,7 +36,7 @@ abstract class TransformedListIterator<F extends @Nullable Object, T extends @Nu } private ListIterator<? extends F> backingIterator() { - return Iterators.cast(backingIterator); + return (ListIterator<? extends F>) backingIterator; } @Override diff --git a/guava/src/com/google/common/collect/TreeMultiset.java b/guava/src/com/google/common/collect/TreeMultiset.java index 7efafd8ec..8024f5ebb 100644 --- a/guava/src/com/google/common/collect/TreeMultiset.java +++ b/guava/src/com/google/common/collect/TreeMultiset.java @@ -1088,7 +1088,7 @@ public final class TreeMultiset<E extends @Nullable Object> extends AbstractSort stream.defaultReadObject(); @SuppressWarnings("unchecked") // reading data stored by writeObject - Comparator<? super E> comparator = (Comparator<? super E>) stream.readObject(); + Comparator<? super E> comparator = (Comparator<? super E>) requireNonNull(stream.readObject()); Serialization.getFieldSetter(AbstractSortedMultiset.class, "comparator").set(this, comparator); Serialization.getFieldSetter(TreeMultiset.class, "range") .set(this, GeneralRange.all(comparator)); diff --git a/guava/src/com/google/common/escape/Platform.java b/guava/src/com/google/common/escape/Platform.java index dc6610c04..67efe4551 100644 --- a/guava/src/com/google/common/escape/Platform.java +++ b/guava/src/com/google/common/escape/Platform.java @@ -14,6 +14,8 @@ package com.google.common.escape; +import static java.util.Objects.requireNonNull; + import com.google.common.annotations.GwtCompatible; /** @@ -28,7 +30,8 @@ final class Platform { /** Returns a thread-local 1024-char array. */ static char[] charBufferFromThreadLocal() { - return DEST_TL.get(); + // requireNonNull accommodates Android's @RecentlyNullable annotation on ThreadLocal.get + return requireNonNull(DEST_TL.get()); } /** diff --git a/guava/src/com/google/common/eventbus/Dispatcher.java b/guava/src/com/google/common/eventbus/Dispatcher.java index 412bb789e..44f7c46ba 100644 --- a/guava/src/com/google/common/eventbus/Dispatcher.java +++ b/guava/src/com/google/common/eventbus/Dispatcher.java @@ -15,6 +15,7 @@ package com.google.common.eventbus; import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import com.google.common.collect.Queues; import java.util.Iterator; @@ -97,7 +98,8 @@ abstract class Dispatcher { void dispatch(Object event, Iterator<Subscriber> subscribers) { checkNotNull(event); checkNotNull(subscribers); - Queue<Event> queueForThread = queue.get(); + // requireNonNull accommodates Android's @RecentlyNullable annotation on ThreadLocal.get + Queue<Event> queueForThread = requireNonNull(queue.get()); queueForThread.offer(new Event(event, subscribers)); if (!dispatching.get()) { diff --git a/guava/src/com/google/common/graph/StandardMutableValueGraph.java b/guava/src/com/google/common/graph/StandardMutableValueGraph.java index 0ea641a5b..1ad474083 100644 --- a/guava/src/com/google/common/graph/StandardMutableValueGraph.java +++ b/guava/src/com/google/common/graph/StandardMutableValueGraph.java @@ -24,6 +24,7 @@ import static com.google.common.graph.Graphs.checkNonNegative; import static com.google.common.graph.Graphs.checkPositive; import static java.util.Objects.requireNonNull; +import com.google.common.collect.ImmutableList; import com.google.errorprone.annotations.CanIgnoreReturnValue; import javax.annotation.CheckForNull; @@ -136,17 +137,21 @@ final class StandardMutableValueGraph<N, V> extends StandardValueGraph<N, V> } } - for (N successor : connections.successors()) { + for (N successor : ImmutableList.copyOf(connections.successors())) { // requireNonNull is safe because the node is a successor. requireNonNull(nodeConnections.getWithoutCaching(successor)).removePredecessor(node); + requireNonNull(connections.removeSuccessor(successor)); --edgeCount; } if (isDirected()) { // In undirected graphs, the successor and predecessor sets are equal. - for (N predecessor : connections.predecessors()) { + // Since views are returned, we need to copy the predecessors that will be removed. + // Thus we avoid modifying the underlying view while iterating over it. + for (N predecessor : ImmutableList.copyOf(connections.predecessors())) { // requireNonNull is safe because the node is a predecessor. checkState( requireNonNull(nodeConnections.getWithoutCaching(predecessor)).removeSuccessor(node) != null); + connections.removePredecessor(predecessor); --edgeCount; } } diff --git a/guava/src/com/google/common/hash/BloomFilter.java b/guava/src/com/google/common/hash/BloomFilter.java index 3f1079ee8..fb0542f89 100644 --- a/guava/src/com/google/common/hash/BloomFilter.java +++ b/guava/src/com/google/common/hash/BloomFilter.java @@ -597,6 +597,7 @@ public final class BloomFilter<T extends @Nullable Object> implements Predicate< * @throws IOException if the InputStream throws an {@code IOException}, or if its data does not * appear to be a BloomFilter serialized using the {@linkplain #writeTo(OutputStream)} method. */ + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception public static <T extends @Nullable Object> BloomFilter<T> readFrom( InputStream in, Funnel<? super T> funnel) throws IOException { checkNotNull(in, "InputStream"); @@ -621,7 +622,9 @@ public final class BloomFilter<T extends @Nullable Object> implements Predicate< } return new BloomFilter<T>(dataArray, numHashFunctions, funnel, strategy); - } catch (RuntimeException e) { + } catch (IOException e) { + throw e; + } catch (Exception e) { // sneaky checked exception String message = "Unable to deserialize BloomFilter from InputStream." + " strategyOrdinal: " @@ -633,4 +636,6 @@ public final class BloomFilter<T extends @Nullable Object> implements Predicate< throw new IOException(message, e); } } + + private static final long serialVersionUID = 0xcafebabe; } diff --git a/guava/src/com/google/common/io/BaseEncoding.java b/guava/src/com/google/common/io/BaseEncoding.java index 50a8ff7e4..c176d0b00 100644 --- a/guava/src/com/google/common/io/BaseEncoding.java +++ b/guava/src/com/google/common/io/BaseEncoding.java @@ -433,7 +433,7 @@ public abstract class BaseEncoding { return BASE16; } - private static final class Alphabet { + static final class Alphabet { private final String name; // this is meant to be immutable -- don't modify it! private final char[] chars; diff --git a/guava/src/com/google/common/io/TempFileCreator.java b/guava/src/com/google/common/io/TempFileCreator.java index 966323599..769761280 100644 --- a/guava/src/com/google/common/io/TempFileCreator.java +++ b/guava/src/com/google/common/io/TempFileCreator.java @@ -16,17 +16,22 @@ package com.google.common.io; import static com.google.common.base.StandardSystemProperty.JAVA_IO_TMPDIR; import static com.google.common.base.StandardSystemProperty.USER_NAME; +import static com.google.common.base.Throwables.throwIfUnchecked; import static java.nio.file.attribute.AclEntryFlag.DIRECTORY_INHERIT; import static java.nio.file.attribute.AclEntryFlag.FILE_INHERIT; import static java.nio.file.attribute.AclEntryType.ALLOW; import static java.nio.file.attribute.PosixFilePermissions.asFileAttribute; +import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.j2objc.annotations.J2ObjCIncompatible; import java.io.File; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.nio.file.FileSystems; import java.nio.file.Paths; import java.nio.file.attribute.AclEntry; @@ -98,6 +103,20 @@ abstract class TempFileCreator { return new JavaIoCreator(); } + /** + * Creates the permissions normally used for Windows filesystems, looking up the user afresh, even + * if previous calls have initialized the {@code PermissionSupplier} fields. + * + * <p>This lets us test the effects of different values of the {@code user.name} system property + * without needing a separate VM or classloader. + */ + @IgnoreJRERequirement // used only when Path is available (and only from tests) + @VisibleForTesting + static void testMakingUserPermissionsFromScratch() throws IOException { + // All we're testing is whether it throws. + FileAttribute<?> unused = JavaNioCreator.userPermissions().get(); + } + @IgnoreJRERequirement // used only when Path is available private static final class JavaNioCreator extends TempFileCreator { @Override @@ -150,7 +169,7 @@ abstract class TempFileCreator { UserPrincipal user = FileSystems.getDefault() .getUserPrincipalLookupService() - .lookupPrincipalByName(USER_NAME.value()); + .lookupPrincipalByName(getUsername()); ImmutableList<AclEntry> acl = ImmutableList.of( AclEntry.newBuilder() @@ -179,6 +198,62 @@ abstract class TempFileCreator { }; } } + + private static String getUsername() { + /* + * https://github.com/google/guava/issues/6634: ProcessHandle has more accurate information, + * but that class isn't available under all environments that we support. We use it if + * available and fall back if not. + */ + String fromSystemProperty = requireNonNull(USER_NAME.value()); + + try { + Class<?> processHandleClass = Class.forName("java.lang.ProcessHandle"); + Class<?> processHandleInfoClass = Class.forName("java.lang.ProcessHandle$Info"); + Class<?> optionalClass = Class.forName("java.util.Optional"); + /* + * We don't *need* to use reflection to access Optional: It's available on all JDKs we + * support, and Android code won't get this far, anyway, because ProcessHandle is + * unavailable. But given how much other reflection we're using, we might as well use it + * here, too, so that we don't need to also suppress an AndroidApiChecker error. + */ + + Method currentMethod = processHandleClass.getMethod("current"); + Method infoMethod = processHandleClass.getMethod("info"); + Method userMethod = processHandleInfoClass.getMethod("user"); + Method orElseMethod = optionalClass.getMethod("orElse", Object.class); + + Object current = currentMethod.invoke(null); + Object info = infoMethod.invoke(current); + Object user = userMethod.invoke(info); + return (String) requireNonNull(orElseMethod.invoke(user, fromSystemProperty)); + } catch (ClassNotFoundException runningUnderAndroidOrJava8) { + /* + * I'm not sure that we could actually get here for *Android*: I would expect us to enter + * the POSIX code path instead. And if we tried this code path, we'd have trouble unless we + * were running under a new enough version of Android to support NIO. + * + * So this is probably just the "Windows Java 8" case. In that case, if we wanted *another* + * layer of fallback before consulting the system property, we could try + * com.sun.security.auth.module.NTSystem. + * + * But for now, we use the value from the system property as our best guess. + */ + return fromSystemProperty; + } catch (InvocationTargetException e) { + throwIfUnchecked(e.getCause()); // in case it's an Error or something + return fromSystemProperty; // should be impossible + } catch (NoSuchMethodException shouldBeImpossible) { + return fromSystemProperty; + } catch (IllegalAccessException shouldBeImpossible) { + /* + * We don't merge these into `catch (ReflectiveOperationException ...)` or an equivalent + * multicatch because ReflectiveOperationException isn't available under Android: + * b/124188803 + */ + return fromSystemProperty; + } + } } private static final class JavaIoCreator extends TempFileCreator { diff --git a/guava/src/com/google/common/net/HostAndPort.java b/guava/src/com/google/common/net/HostAndPort.java index a27eb65ff..0ec28198c 100644 --- a/guava/src/com/google/common/net/HostAndPort.java +++ b/guava/src/com/google/common/net/HostAndPort.java @@ -209,7 +209,7 @@ public final class HostAndPort implements Serializable { /** * Parses a bracketed host-port string, throwing IllegalArgumentException if parsing fails. * - * @param hostPortString the full bracketed host-port specification. Post might not be specified. + * @param hostPortString the full bracketed host-port specification. Port might not be specified. * @return an array with 2 strings: host and port, in that order. * @throws IllegalArgumentException if parsing the bracketed host-port string fails. */ diff --git a/guava/src/com/google/common/net/HttpHeaders.java b/guava/src/com/google/common/net/HttpHeaders.java index 4c1f865b5..714cb313c 100644 --- a/guava/src/com/google/common/net/HttpHeaders.java +++ b/guava/src/com/google/common/net/HttpHeaders.java @@ -855,6 +855,25 @@ public final class HttpHeaders { * @since 32.0.0 */ public static final String OBSERVE_BROWSING_TOPICS = "Observe-Browsing-Topics"; + + /** + * The HTTP <a + * href="https://wicg.github.io/turtledove/#handling-direct-from-seller-signals">{@code + * Sec-Ad-Auction-Fetch}</a> header field name. + * + * @since 33.0.0 + */ + public static final String SEC_AD_AUCTION_FETCH = "Sec-Ad-Auction-Fetch"; + + /** + * The HTTP <a + * href="https://wicg.github.io/turtledove/#handling-direct-from-seller-signals">{@code + * Ad-Auction-Signals}</a> header field name. + * + * @since 33.0.0 + */ + public static final String AD_AUCTION_SIGNALS = "Ad-Auction-Signals"; + /** * The HTTP <a href="https://tools.ietf.org/html/rfc8586">{@code CDN-Loop}</a> header field name. * diff --git a/guava/src/com/google/common/net/InetAddresses.java b/guava/src/com/google/common/net/InetAddresses.java index 6d8309381..540a21986 100644 --- a/guava/src/com/google/common/net/InetAddresses.java +++ b/guava/src/com/google/common/net/InetAddresses.java @@ -16,6 +16,7 @@ package com.google.common.net; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; @@ -409,7 +410,8 @@ public final class InetAddresses { checkNotNull(ip); if (ip instanceof Inet4Address) { // For IPv4, Java's formatting is good enough. - return ip.getHostAddress(); + // requireNonNull accommodates Android's @RecentlyNullable annotation on getHostAddress + return requireNonNull(ip.getHostAddress()); } checkArgument(ip instanceof Inet6Address); byte[] bytes = ip.getAddress(); diff --git a/guava/src/com/google/common/net/MediaType.java b/guava/src/com/google/common/net/MediaType.java index c7da53491..99d47dca7 100644 --- a/guava/src/com/google/common/net/MediaType.java +++ b/guava/src/com/google/common/net/MediaType.java @@ -1052,15 +1052,13 @@ public final class MediaType { Tokenizer tokenizer = new Tokenizer(input); try { String type = tokenizer.consumeToken(TOKEN_MATCHER); - tokenizer.consumeCharacter('/'); + consumeSeparator(tokenizer, '/'); String subtype = tokenizer.consumeToken(TOKEN_MATCHER); ImmutableListMultimap.Builder<String, String> parameters = ImmutableListMultimap.builder(); while (tokenizer.hasMore()) { - tokenizer.consumeTokenIfPresent(LINEAR_WHITE_SPACE); - tokenizer.consumeCharacter(';'); - tokenizer.consumeTokenIfPresent(LINEAR_WHITE_SPACE); + consumeSeparator(tokenizer, ';'); String attribute = tokenizer.consumeToken(TOKEN_MATCHER); - tokenizer.consumeCharacter('='); + consumeSeparator(tokenizer, '='); String value; if ('"' == tokenizer.previewChar()) { tokenizer.consumeCharacter('"'); @@ -1086,6 +1084,12 @@ public final class MediaType { } } + private static void consumeSeparator(Tokenizer tokenizer, char c) { + tokenizer.consumeTokenIfPresent(LINEAR_WHITE_SPACE); + tokenizer.consumeCharacter(c); + tokenizer.consumeTokenIfPresent(LINEAR_WHITE_SPACE); + } + private static final class Tokenizer { final String input; int position = 0; diff --git a/guava/src/com/google/common/primitives/Doubles.java b/guava/src/com/google/common/primitives/Doubles.java index f5133ecde..7fcbae957 100644 --- a/guava/src/com/google/common/primitives/Doubles.java +++ b/guava/src/com/google/common/primitives/Doubles.java @@ -289,7 +289,7 @@ public final class Doubles extends DoublesMethodsForWeb { private static final class DoubleConverter extends Converter<String, Double> implements Serializable { - static final DoubleConverter INSTANCE = new DoubleConverter(); + static final Converter<String, Double> INSTANCE = new DoubleConverter(); @Override protected Double doForward(String value) { diff --git a/guava/src/com/google/common/primitives/Floats.java b/guava/src/com/google/common/primitives/Floats.java index d7f156b1e..c42f2f1ee 100644 --- a/guava/src/com/google/common/primitives/Floats.java +++ b/guava/src/com/google/common/primitives/Floats.java @@ -284,7 +284,7 @@ public final class Floats extends FloatsMethodsForWeb { private static final class FloatConverter extends Converter<String, Float> implements Serializable { - static final FloatConverter INSTANCE = new FloatConverter(); + static final Converter<String, Float> INSTANCE = new FloatConverter(); @Override protected Float doForward(String value) { diff --git a/guava/src/com/google/common/primitives/Ints.java b/guava/src/com/google/common/primitives/Ints.java index 4eaa5a6a4..afd4a7b4a 100644 --- a/guava/src/com/google/common/primitives/Ints.java +++ b/guava/src/com/google/common/primitives/Ints.java @@ -337,7 +337,7 @@ public final class Ints extends IntsMethodsForWeb { private static final class IntConverter extends Converter<String, Integer> implements Serializable { - static final IntConverter INSTANCE = new IntConverter(); + static final Converter<String, Integer> INSTANCE = new IntConverter(); @Override protected Integer doForward(String value) { diff --git a/guava/src/com/google/common/primitives/Longs.java b/guava/src/com/google/common/primitives/Longs.java index 8369973cc..7c5a5d3bb 100644 --- a/guava/src/com/google/common/primitives/Longs.java +++ b/guava/src/com/google/common/primitives/Longs.java @@ -440,7 +440,7 @@ public final class Longs { } private static final class LongConverter extends Converter<String, Long> implements Serializable { - static final LongConverter INSTANCE = new LongConverter(); + static final Converter<String, Long> INSTANCE = new LongConverter(); @Override protected Long doForward(String value) { diff --git a/guava/src/com/google/common/primitives/Shorts.java b/guava/src/com/google/common/primitives/Shorts.java index 85ffd3ba8..e7cc8538b 100644 --- a/guava/src/com/google/common/primitives/Shorts.java +++ b/guava/src/com/google/common/primitives/Shorts.java @@ -335,7 +335,7 @@ public final class Shorts extends ShortsMethodsForWeb { private static final class ShortConverter extends Converter<String, Short> implements Serializable { - static final ShortConverter INSTANCE = new ShortConverter(); + static final Converter<String, Short> INSTANCE = new ShortConverter(); @Override protected Short doForward(String value) { diff --git a/guava/src/com/google/common/reflect/Invokable.java b/guava/src/com/google/common/reflect/Invokable.java index 29f4a4ed9..2e2c04193 100644 --- a/guava/src/com/google/common/reflect/Invokable.java +++ b/guava/src/com/google/common/reflect/Invokable.java @@ -117,13 +117,14 @@ public abstract class Invokable<T, R> implements AnnotatedElement, Member { } /** See {@link java.lang.reflect.AccessibleObject#trySetAccessible()}. */ + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception public final boolean trySetAccessible() { // We can't call accessibleObject.trySetAccessible since that was added in Java 9 and this code // should work on Java 8. So we emulate it this way. try { accessibleObject.setAccessible(true); return true; - } catch (RuntimeException e) { + } catch (Exception e) { // sneaky checked exception return false; } } @@ -341,8 +342,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 +355,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 +387,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 +476,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(); } diff --git a/guava/src/com/google/common/reflect/Parameter.java b/guava/src/com/google/common/reflect/Parameter.java index c80d18571..e0e244b05 100644 --- a/guava/src/com/google/common/reflect/Parameter.java +++ b/guava/src/com/google/common/reflect/Parameter.java @@ -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); } diff --git a/guava/src/com/google/common/util/concurrent/AbstractCatchingFuture.java b/guava/src/com/google/common/util/concurrent/AbstractCatchingFuture.java index e5df53835..8fa650028 100644 --- a/guava/src/com/google/common/util/concurrent/AbstractCatchingFuture.java +++ b/guava/src/com/google/common/util/concurrent/AbstractCatchingFuture.java @@ -108,8 +108,8 @@ abstract class AbstractCatchingFuture< + e.getClass() + " without a cause"); } - } catch (RuntimeException | Error e) { // this includes cancellation exception - throwable = e; + } catch (Throwable t) { // this includes CancellationException and sneaky checked exception + throwable = t; } if (throwable == null) { diff --git a/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java b/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java index c52f9d456..512d80955 100644 --- a/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java +++ b/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java @@ -24,7 +24,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.logging.Level; -import java.util.logging.Logger; /** * Base class for services that can implement {@link #startUp}, {@link #run} and {@link #shutDown} @@ -38,8 +37,7 @@ import java.util.logging.Logger; @J2ktIncompatible @ElementTypesAreNonnullByDefault public abstract class AbstractExecutionThreadService implements Service { - private static final Logger logger = - Logger.getLogger(AbstractExecutionThreadService.class.getName()); + private static final LazyLogger logger = new LazyLogger(AbstractExecutionThreadService.class); /* use AbstractService for state management */ private final Service delegate = @@ -66,10 +64,12 @@ public abstract class AbstractExecutionThreadService implements Service { // TODO(lukes): if guava ever moves to java7, this would be a good // candidate for a suppressed exception, or maybe we could generalize // Closer.Suppressor - logger.log( - Level.WARNING, - "Error while attempting to shut down the service after failure.", - ignored); + logger + .get() + .log( + Level.WARNING, + "Error while attempting to shut down the service after failure.", + ignored); } notifyFailed(t); return; diff --git a/guava/src/com/google/common/util/concurrent/AbstractFuture.java b/guava/src/com/google/common/util/concurrent/AbstractFuture.java index 42ec5264c..a886f10c2 100644 --- a/guava/src/com/google/common/util/concurrent/AbstractFuture.java +++ b/guava/src/com/google/common/util/concurrent/AbstractFuture.java @@ -42,7 +42,6 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.concurrent.locks.LockSupport; import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.CheckForNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -141,8 +140,7 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna } } - // Logger to log exceptions caught when running listeners. - private static final Logger log = Logger.getLogger(AbstractFuture.class.getName()); + static final LazyLogger log = new LazyLogger(AbstractFuture.class); // A heuristic for timed gets. If the remaining timeout is less than this, spin instead of // blocking. This value is what AbstractQueuedSynchronizer uses. @@ -157,7 +155,7 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna try { helper = new UnsafeAtomicHelper(); - } catch (RuntimeException | Error unsafeFailure) { + } catch (Exception | Error unsafeFailure) { // sneaky checked exception thrownUnsafeFailure = unsafeFailure; // catch absolutely everything and fall through to our 'SafeAtomicHelper' // The access control checks that ARFU does means the caller class has to be AbstractFuture @@ -170,7 +168,8 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna newUpdater(AbstractFuture.class, Waiter.class, "waiters"), newUpdater(AbstractFuture.class, Listener.class, "listeners"), newUpdater(AbstractFuture.class, Object.class, "value")); - } catch (RuntimeException | Error atomicReferenceFieldUpdaterFailure) { + } catch (Exception // sneaky checked exception + | Error atomicReferenceFieldUpdaterFailure) { // Some Android 5.0.x Samsung devices have bugs in JDK reflection APIs that cause // getDeclaredField to throw a NoSuchFieldException when the field is definitely there. // For these users fallback to a suboptimal implementation, based on synchronized. This will @@ -189,9 +188,12 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna // Log after all static init is finished; if an installed logger uses any Futures methods, it // shouldn't break in cases where reflection is missing/broken. if (thrownAtomicReferenceFieldUpdaterFailure != null) { - log.log(Level.SEVERE, "UnsafeAtomicHelper is broken!", thrownUnsafeFailure); - log.log( - Level.SEVERE, "SafeAtomicHelper is broken!", thrownAtomicReferenceFieldUpdaterFailure); + log.get().log(Level.SEVERE, "UnsafeAtomicHelper is broken!", thrownUnsafeFailure); + log.get() + .log( + Level.SEVERE, + "SafeAtomicHelper is broken!", + thrownAtomicReferenceFieldUpdaterFailure); } } @@ -864,14 +866,16 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna // since all we are doing is unpacking a completed future which should be fast. try { future.addListener(valueToSet, DirectExecutor.INSTANCE); - } catch (RuntimeException | Error t) { + } catch (Throwable t) { + // Any Exception is either a RuntimeException or sneaky checked exception. + // // addListener has thrown an exception! SetFuture.run can't throw any exceptions so this // must have been caused by addListener itself. The most likely explanation is a // misconfigured mock. Try to switch to Failure. Failure failure; try { failure = new Failure(t); - } catch (RuntimeException | Error oomMostLikely) { + } catch (Exception | Error oomMostLikely) { // sneaky checked exception failure = Failure.FALLBACK_INSTANCE; } // Note: The only way this CAS could fail is if cancel() has raced with us. That is ok. @@ -966,7 +970,7 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna cancellation)); } return new Cancellation(false, cancellation); - } catch (RuntimeException | Error t) { + } catch (Exception | Error t) { // sneaky checked exception return new Failure(t); } } @@ -1190,6 +1194,7 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna return null; } + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception private void addPendingString(StringBuilder builder) { // Capture current builder length so it can be truncated if this future ends up completing while // the toString is being calculated @@ -1206,7 +1211,9 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna String pendingDescription; try { pendingDescription = Strings.emptyToNull(pendingToString()); - } catch (RuntimeException | StackOverflowError e) { + } catch (Exception | StackOverflowError e) { + // Any Exception is either a RuntimeException or sneaky checked exception. + // // Don't call getMessage or toString() on the exception, in case the exception thrown by the // subclass is implemented with bugs similar to the subclass. pendingDescription = "Exception thrown from implementation: " + e.getClass(); @@ -1225,6 +1232,7 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna } } + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception private void addDoneString(StringBuilder builder) { try { V value = getUninterruptibly(this); @@ -1235,7 +1243,7 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna builder.append("FAILURE, cause=[").append(e.getCause()).append("]"); } catch (CancellationException e) { builder.append("CANCELLED"); // shouldn't be reachable - } catch (RuntimeException e) { + } catch (Exception e) { // sneaky checked exception builder.append("UNKNOWN, cause=[").append(e.getClass()).append(" thrown from get()]"); } } @@ -1259,6 +1267,7 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna } /** Helper for printing user supplied objects into our toString method. */ + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception private void appendUserObject(StringBuilder builder, @CheckForNull Object o) { // This is some basic recursion detection for when people create cycles via set/setFuture or // when deep chains of futures exist resulting in a StackOverflowException. We could detect @@ -1270,7 +1279,9 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna } else { builder.append(o); } - } catch (RuntimeException | StackOverflowError e) { + } catch (Exception | StackOverflowError e) { + // Any Exception is either a RuntimeException or sneaky checked exception. + // // Don't call getMessage or toString() on the exception, in case the exception thrown by the // user object is implemented with bugs similar to the user object. builder.append("Exception thrown from implementation: ").append(e.getClass()); @@ -1281,17 +1292,22 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna * Submits the given runnable to the given {@link Executor} catching and logging all {@linkplain * RuntimeException runtime exceptions} thrown by the executor. */ + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception private static void executeListener(Runnable runnable, Executor executor) { try { executor.execute(runnable); - } catch (RuntimeException e) { + } catch (Exception e) { // sneaky checked exception // Log it and keep going -- bad runnable and/or executor. Don't punish the other runnables if // we're given a bad one. We only catch RuntimeException because we want Errors to propagate // up. - log.log( - Level.SEVERE, - "RuntimeException while executing runnable " + runnable + " with executor " + executor, - e); + log.get() + .log( + Level.SEVERE, + "RuntimeException while executing runnable " + + runnable + + " with executor " + + executor, + e); } } @@ -1371,8 +1387,6 @@ public abstract class AbstractFuture<V extends @Nullable Object> extends Interna UNSAFE = unsafe; } catch (NoSuchFieldException e) { throw new RuntimeException(e); - } catch (RuntimeException e) { - throw e; } } diff --git a/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java b/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java index 164a6dbb4..2529d4749 100644 --- a/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java +++ b/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java @@ -40,7 +40,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.CheckForNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -105,7 +104,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; @J2ktIncompatible @ElementTypesAreNonnullByDefault public abstract class AbstractScheduledService implements Service { - private static final Logger logger = Logger.getLogger(AbstractScheduledService.class.getName()); + private static final LazyLogger logger = new LazyLogger(AbstractScheduledService.class); /** * A scheduler defines the policy for how the {@link AbstractScheduledService} should run its @@ -239,10 +238,12 @@ public abstract class AbstractScheduledService implements Service { shutDown(); } catch (Exception ignored) { restoreInterruptIfIsInterruptedException(ignored); - logger.log( - Level.WARNING, - "Error while attempting to shut down the service after failure.", - ignored); + logger + .get() + .log( + Level.WARNING, + "Error while attempting to shut down the service after failure.", + ignored); } notifyFailed(t); // requireNonNull is safe now, just as it was above. @@ -606,7 +607,9 @@ public abstract class AbstractScheduledService implements Service { lock.lock(); try { toReturn = initializeOrUpdateCancellationDelegate(schedule); - } catch (RuntimeException | Error e) { + } catch (Throwable e) { + // Any Exception is either a RuntimeException or sneaky checked exception. + // // If an exception is thrown by the subclass then we need to make sure that the service // notices and transitions to the FAILED state. We do it by calling notifyFailed directly // because the service does not monitor the state of the future so if the exception is not diff --git a/guava/src/com/google/common/util/concurrent/AbstractTransformFuture.java b/guava/src/com/google/common/util/concurrent/AbstractTransformFuture.java index 5581b5fae..3c5f30b63 100644 --- a/guava/src/com/google/common/util/concurrent/AbstractTransformFuture.java +++ b/guava/src/com/google/common/util/concurrent/AbstractTransformFuture.java @@ -66,6 +66,7 @@ abstract class AbstractTransformFuture< } @Override + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception public final void run() { ListenableFuture<? extends I> localInputFuture = inputFuture; F localFunction = function; @@ -104,7 +105,7 @@ abstract class AbstractTransformFuture< // Set the cause of the exception as this future's exception. setException(e.getCause()); return; - } catch (RuntimeException e) { + } catch (Exception e) { // sneaky checked exception // Bug in inputFuture.get(). Propagate to the output Future so that its consumers don't hang. setException(e); return; diff --git a/guava/src/com/google/common/util/concurrent/AggregateFuture.java b/guava/src/com/google/common/util/concurrent/AggregateFuture.java index ec96cbb89..353477416 100644 --- a/guava/src/com/google/common/util/concurrent/AggregateFuture.java +++ b/guava/src/com/google/common/util/concurrent/AggregateFuture.java @@ -30,7 +30,6 @@ import com.google.errorprone.annotations.OverridingMethodsMustInvokeSuper; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; -import java.util.logging.Logger; import javax.annotation.CheckForNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -44,7 +43,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; @ElementTypesAreNonnullByDefault abstract class AggregateFuture<InputT extends @Nullable Object, OutputT extends @Nullable Object> extends AggregateFutureState<OutputT> { - private static final Logger logger = Logger.getLogger(AggregateFuture.class.getName()); + private static final LazyLogger logger = new LazyLogger(AggregateFuture.class); /** * The input futures. After {@link #init}, this field is read only by {@link #afterDone()} (to @@ -230,7 +229,7 @@ abstract class AggregateFuture<InputT extends @Nullable Object, OutputT extends (throwable instanceof Error) ? "Input Future failed with Error" : "Got more than one input Future failure. Logging failures after the first"; - logger.log(SEVERE, message, throwable); + logger.get().log(SEVERE, message, throwable); } @Override @@ -268,7 +267,7 @@ abstract class AggregateFuture<InputT extends @Nullable Object, OutputT extends collectOneValue(index, getDone(future)); } catch (ExecutionException e) { handleException(e.getCause()); - } catch (RuntimeException | Error t) { + } catch (Throwable t) { // sneaky checked exception handleException(t); } } diff --git a/guava/src/com/google/common/util/concurrent/AggregateFutureState.java b/guava/src/com/google/common/util/concurrent/AggregateFutureState.java index 7bdec0135..5816abf05 100644 --- a/guava/src/com/google/common/util/concurrent/AggregateFutureState.java +++ b/guava/src/com/google/common/util/concurrent/AggregateFutureState.java @@ -25,7 +25,6 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.CheckForNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -51,7 +50,7 @@ abstract class AggregateFutureState<OutputT extends @Nullable Object> private static final AtomicHelper ATOMIC_HELPER; - private static final Logger log = Logger.getLogger(AggregateFutureState.class.getName()); + private static final LazyLogger log = new LazyLogger(AggregateFutureState.class); static { AtomicHelper helper; @@ -61,7 +60,7 @@ abstract class AggregateFutureState<OutputT extends @Nullable Object> new SafeAtomicHelper( newUpdater(AggregateFutureState.class, Set.class, "seenExceptions"), newUpdater(AggregateFutureState.class, "remaining")); - } catch (RuntimeException | Error reflectionFailure) { + } catch (Throwable reflectionFailure) { // sneaky checked exception // Some Android 5.0.x Samsung devices have bugs in JDK reflection APIs that cause // getDeclaredField to throw a NoSuchFieldException when the field is definitely there. // For these users fallback to a suboptimal implementation, based on synchronized. This will @@ -73,7 +72,7 @@ abstract class AggregateFutureState<OutputT extends @Nullable Object> // Log after all static init is finished; if an installed logger uses any Futures methods, it // shouldn't break in cases where reflection is missing/broken. if (thrownReflectionFailure != null) { - log.log(Level.SEVERE, "SafeAtomicHelper is broken!", thrownReflectionFailure); + log.get().log(Level.SEVERE, "SafeAtomicHelper is broken!", thrownReflectionFailure); } } @@ -159,7 +158,7 @@ abstract class AggregateFutureState<OutputT extends @Nullable Object> } private static final class SafeAtomicHelper extends AtomicHelper { - final AtomicReferenceFieldUpdater<AggregateFutureState<?>, Set<Throwable>> + final AtomicReferenceFieldUpdater<AggregateFutureState<?>, @Nullable Set<Throwable>> seenExceptionsUpdater; final AtomicIntegerFieldUpdater<AggregateFutureState<?>> remainingCountUpdater; @@ -169,7 +168,7 @@ abstract class AggregateFutureState<OutputT extends @Nullable Object> AtomicReferenceFieldUpdater seenExceptionsUpdater, AtomicIntegerFieldUpdater remainingCountUpdater) { this.seenExceptionsUpdater = - (AtomicReferenceFieldUpdater<AggregateFutureState<?>, Set<Throwable>>) + (AtomicReferenceFieldUpdater<AggregateFutureState<?>, @Nullable Set<Throwable>>) seenExceptionsUpdater; this.remainingCountUpdater = (AtomicIntegerFieldUpdater<AggregateFutureState<?>>) remainingCountUpdater; diff --git a/guava/src/com/google/common/util/concurrent/AtomicLongMap.java b/guava/src/com/google/common/util/concurrent/AtomicLongMap.java index 28481cca5..4ede5d606 100644 --- a/guava/src/com/google/common/util/concurrent/AtomicLongMap.java +++ b/guava/src/com/google/common/util/concurrent/AtomicLongMap.java @@ -17,6 +17,7 @@ package com.google.common.util.concurrent; import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.J2ktIncompatible; @@ -147,8 +148,11 @@ public final class AtomicLongMap<K> implements Serializable { @CanIgnoreReturnValue public long updateAndGet(K key, LongUnaryOperator updaterFunction) { checkNotNull(updaterFunction); - return map.compute( - key, (k, value) -> updaterFunction.applyAsLong((value == null) ? 0L : value.longValue())); + Long result = + map.compute( + key, + (k, value) -> updaterFunction.applyAsLong((value == null) ? 0L : value.longValue())); + return requireNonNull(result); } /** @@ -329,7 +333,7 @@ public final class AtomicLongMap<K> implements Serializable { return oldValue; } }); - return noValue.get() ? 0L : result.longValue(); + return noValue.get() ? 0L : requireNonNull(result).longValue(); } /** diff --git a/guava/src/com/google/common/util/concurrent/ClosingFuture.java b/guava/src/com/google/common/util/concurrent/ClosingFuture.java index 79aa0aa0e..efdf56d8a 100644 --- a/guava/src/com/google/common/util/concurrent/ClosingFuture.java +++ b/guava/src/com/google/common/util/concurrent/ClosingFuture.java @@ -58,7 +58,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.Future; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicReference; -import java.util.logging.Logger; import javax.annotation.CheckForNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -196,7 +195,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; // TODO(dpb): GWT compatibility. public final class ClosingFuture<V extends @Nullable Object> { - private static final Logger logger = Logger.getLogger(ClosingFuture.class.getName()); + private static final LazyLogger logger = new LazyLogger(ClosingFuture.class); /** * An object that can capture objects to be closed later, when a {@link ClosingFuture} pipeline is @@ -681,7 +680,7 @@ public final class ClosingFuture<V extends @Nullable Object> { * * <p>After calling this method, you may not call {@link #finishToFuture()}, {@link * #finishToValueAndCloser(ValueAndCloserConsumer, Executor)}, or any other derivation method on - * this {@code ClosingFuture}. + * the original {@code ClosingFuture} instance. * * @param function transforms the value of this step to the value of the derived step * @param executor executor to run the function in @@ -774,7 +773,7 @@ public final class ClosingFuture<V extends @Nullable Object> { * * <p>After calling this method, you may not call {@link #finishToFuture()}, {@link * #finishToValueAndCloser(ValueAndCloserConsumer, Executor)}, or any other derivation method on - * this {@code ClosingFuture}. + * the original {@code ClosingFuture} instance. * * @param function transforms the value of this step to a {@code ClosingFuture} with the value of * the derived step @@ -865,7 +864,7 @@ public final class ClosingFuture<V extends @Nullable Object> { * * <p>After calling this method, you may not call {@link #finishToFuture()}, {@link * #finishToValueAndCloser(ValueAndCloserConsumer, Executor)}, or any other derivation method on - * this {@code ClosingFuture}. + * the original {@code ClosingFuture} instance. * * @param exceptionType the exception type that triggers use of {@code fallback}. The exception * type is matched against this step's exception. "This step's exception" means the cause of @@ -958,7 +957,7 @@ public final class ClosingFuture<V extends @Nullable Object> { * * <p>After calling this method, you may not call {@link #finishToFuture()}, {@link * #finishToValueAndCloser(ValueAndCloserConsumer, Executor)}, or any other derivation method on - * this {@code ClosingFuture}. + * the original {@code ClosingFuture} instance. * * @param exceptionType the exception type that triggers use of {@code fallback}. The exception * type is matched against this step's exception. "This step's exception" means the cause of @@ -1015,13 +1014,13 @@ public final class ClosingFuture<V extends @Nullable Object> { * * <p>After calling this method, you may not call {@link * #finishToValueAndCloser(ValueAndCloserConsumer, Executor)}, this method, or any other - * derivation method on this {@code ClosingFuture}. + * derivation method on the original {@code ClosingFuture} instance. * * @return a {@link Future} that represents the final value or exception of the pipeline */ public FluentFuture<V> finishToFuture() { if (compareAndUpdateState(OPEN, WILL_CLOSE)) { - logger.log(FINER, "will close {0}", this); + logger.get().log(FINER, "will close {0}", this); future.addListener( new Runnable() { @Override @@ -1060,7 +1059,7 @@ public final class ClosingFuture<V extends @Nullable Object> { * receiver can store the {@link ValueAndCloser} outside the receiver for later synchronous use. * * <p>After calling this method, you may not call {@link #finishToFuture()}, this method again, or - * any other derivation method on this {@code ClosingFuture}. + * any other derivation method on the original {@code ClosingFuture} instance. * * @param consumer a callback whose method will be called (using {@code executor}) when this * operation is done @@ -1121,7 +1120,7 @@ public final class ClosingFuture<V extends @Nullable Object> { */ @CanIgnoreReturnValue public boolean cancel(boolean mayInterruptIfRunning) { - logger.log(FINER, "cancelling {0}", this); + logger.get().log(FINER, "cancelling {0}", this); boolean cancelled = future.cancel(mayInterruptIfRunning); if (cancelled) { close(); @@ -1130,7 +1129,7 @@ public final class ClosingFuture<V extends @Nullable Object> { } private void close() { - logger.log(FINER, "closing {0}", this); + logger.get().log(FINER, "closing {0}", this); closeables.close(); } @@ -2144,7 +2143,7 @@ public final class ClosingFuture<V extends @Nullable Object> { @Override protected void finalize() { if (state.get().equals(OPEN)) { - logger.log(SEVERE, "Uh oh! An open ClosingFuture has leaked and will close: {0}", this); + logger.get().log(SEVERE, "Uh oh! An open ClosingFuture has leaked and will close: {0}", this); FluentFuture<V> unused = finishToFuture(); } } @@ -2159,14 +2158,26 @@ public final class ClosingFuture<V extends @Nullable Object> { try { closeable.close(); } catch (Exception e) { + /* + * In guava-jre, any kind of Exception may be thrown because `closeable` has type + * `AutoCloseable`. + * + * In guava-android, the only kinds of Exception that may be thrown are + * RuntimeException and IOException because `closeable` has type `Closeable`—except + * that we have to account for sneaky checked exception. + */ restoreInterruptIfIsInterruptedException(e); - logger.log(WARNING, "thrown by close()", e); + logger.get().log(WARNING, "thrown by close()", e); } }); } catch (RejectedExecutionException e) { - if (logger.isLoggable(WARNING)) { - logger.log( - WARNING, String.format("while submitting close to %s; will close inline", executor), e); + if (logger.get().isLoggable(WARNING)) { + logger + .get() + .log( + WARNING, + String.format("while submitting close to %s; will close inline", executor), + e); } closeQuietly(closeable, directExecutor()); } diff --git a/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java b/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java index 0ec799cc4..6e2ae47a3 100644 --- a/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java +++ b/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java @@ -41,7 +41,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.CheckForNull; /** @@ -211,7 +210,7 @@ public class CycleDetectingLockFactory { WARN { @Override public void handlePotentialDeadlock(PotentialDeadlockException e) { - logger.log(Level.SEVERE, "Detected potential deadlock", e); + logger.get().log(Level.SEVERE, "Detected potential deadlock", e); } }, @@ -447,7 +446,7 @@ public class CycleDetectingLockFactory { //////// Implementation ///////// - private static final Logger logger = Logger.getLogger(CycleDetectingLockFactory.class.getName()); + private static final LazyLogger logger = new LazyLogger(CycleDetectingLockFactory.class); final Policy policy; @@ -711,7 +710,8 @@ public class CycleDetectingLockFactory { */ private void aboutToAcquire(CycleDetectingLock lock) { if (!lock.isAcquiredByCurrentThread()) { - ArrayList<LockGraphNode> acquiredLockList = acquiredLocks.get(); + // requireNonNull accommodates Android's @RecentlyNullable annotation on ThreadLocal.get + ArrayList<LockGraphNode> acquiredLockList = requireNonNull(acquiredLocks.get()); LockGraphNode node = lock.getLockGraphNode(); node.checkAcquiredLocks(policy, acquiredLockList); acquiredLockList.add(node); @@ -725,7 +725,8 @@ public class CycleDetectingLockFactory { */ private static void lockStateChanged(CycleDetectingLock lock) { if (!lock.isAcquiredByCurrentThread()) { - ArrayList<LockGraphNode> acquiredLockList = acquiredLocks.get(); + // requireNonNull accommodates Android's @RecentlyNullable annotation on ThreadLocal.get + ArrayList<LockGraphNode> acquiredLockList = requireNonNull(acquiredLocks.get()); LockGraphNode node = lock.getLockGraphNode(); // Iterate in reverse because locks are usually locked/unlocked in a // LIFO order. diff --git a/guava/src/com/google/common/util/concurrent/ExecutionList.java b/guava/src/com/google/common/util/concurrent/ExecutionList.java index 645817c4a..10b933aa1 100644 --- a/guava/src/com/google/common/util/concurrent/ExecutionList.java +++ b/guava/src/com/google/common/util/concurrent/ExecutionList.java @@ -21,7 +21,6 @@ import com.google.common.annotations.J2ktIncompatible; import com.google.errorprone.annotations.concurrent.GuardedBy; import java.util.concurrent.Executor; import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.CheckForNull; /** @@ -45,7 +44,7 @@ import javax.annotation.CheckForNull; @ElementTypesAreNonnullByDefault public final class ExecutionList { /** Logger to log exceptions caught when running runnables. */ - private static final Logger log = Logger.getLogger(ExecutionList.class.getName()); + private static final LazyLogger log = new LazyLogger(ExecutionList.class); /** * The runnable, executor pairs to execute. This acts as a stack threaded through the {@link @@ -140,17 +139,22 @@ public final class ExecutionList { * Submits the given runnable to the given {@link Executor} catching and logging all {@linkplain * RuntimeException runtime exceptions} thrown by the executor. */ + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception private static void executeListener(Runnable runnable, Executor executor) { try { executor.execute(runnable); - } catch (RuntimeException e) { + } catch (Exception e) { // sneaky checked exception // Log it and keep going -- bad runnable and/or executor. Don't punish the other runnables if // we're given a bad one. We only catch RuntimeException because we want Errors to propagate // up. - log.log( - Level.SEVERE, - "RuntimeException while executing runnable " + runnable + " with executor " + executor, - e); + log.get() + .log( + Level.SEVERE, + "RuntimeException while executing runnable " + + runnable + + " with executor " + + executor, + e); } } diff --git a/guava/src/com/google/common/util/concurrent/FakeTimeLimiter.java b/guava/src/com/google/common/util/concurrent/FakeTimeLimiter.java index 1c16cfb14..0f8a17894 100644 --- a/guava/src/com/google/common/util/concurrent/FakeTimeLimiter.java +++ b/guava/src/com/google/common/util/concurrent/FakeTimeLimiter.java @@ -77,12 +77,13 @@ public final class FakeTimeLimiter implements TimeLimiter { } @Override + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception public void runWithTimeout(Runnable runnable, long timeoutDuration, TimeUnit timeoutUnit) { checkNotNull(runnable); checkNotNull(timeoutUnit); try { runnable.run(); - } catch (RuntimeException e) { + } catch (Exception e) { // sneaky checked exception throw new UncheckedExecutionException(e); } catch (Error e) { throw new ExecutionError(e); diff --git a/guava/src/com/google/common/util/concurrent/Futures.java b/guava/src/com/google/common/util/concurrent/Futures.java index 31889609a..6e8d20193 100644 --- a/guava/src/com/google/common/util/concurrent/Futures.java +++ b/guava/src/com/google/common/util/concurrent/Futures.java @@ -545,7 +545,8 @@ public final class Futures extends GwtFuturesCatchingSpecialization { private O applyTransformation(I input) throws ExecutionException { try { return function.apply(input); - } catch (RuntimeException | Error t) { + } catch (Throwable t) { + // Any Exception is either a RuntimeException or sneaky checked exception. throw new ExecutionException(t); } } @@ -1126,7 +1127,8 @@ public final class Futures extends GwtFuturesCatchingSpecialization { } catch (ExecutionException e) { callback.onFailure(e.getCause()); return; - } catch (RuntimeException | Error e) { + } catch (Throwable e) { + // Any Exception is either a RuntimeException or sneaky checked exception. callback.onFailure(e); return; } @@ -1202,10 +1204,10 @@ public final class Futures extends GwtFuturesCatchingSpecialization { * * <p>Instances of {@code exceptionClass} are created by choosing an arbitrary public constructor * that accepts zero or more arguments, all of type {@code String} or {@code Throwable} - * (preferring constructors with at least one {@code String}) and calling the constructor via - * reflection. If the exception did not already have a cause, one is set by calling {@link - * Throwable#initCause(Throwable)} on it. If no such constructor exists, an {@code - * IllegalArgumentException} is thrown. + * (preferring constructors with at least one {@code String}, then preferring constructors with at + * least one {@code Throwable}) and calling the constructor via reflection. If the exception did + * not already have a cause, one is set by calling {@link Throwable#initCause(Throwable)} on it. + * If no such constructor exists, an {@code IllegalArgumentException} is thrown. * * @throws X if {@code get} throws any checked exception except for an {@code ExecutionException} * whose cause is not itself a checked exception @@ -1254,10 +1256,10 @@ public final class Futures extends GwtFuturesCatchingSpecialization { * * <p>Instances of {@code exceptionClass} are created by choosing an arbitrary public constructor * that accepts zero or more arguments, all of type {@code String} or {@code Throwable} - * (preferring constructors with at least one {@code String}) and calling the constructor via - * reflection. If the exception did not already have a cause, one is set by calling {@link - * Throwable#initCause(Throwable)} on it. If no such constructor exists, an {@code - * IllegalArgumentException} is thrown. + * (preferring constructors with at least one {@code String}, then preferring constructors with at + * least one {@code Throwable}) and calling the constructor via reflection. If the exception did + * not already have a cause, one is set by calling {@link Throwable#initCause(Throwable)} on it. + * If no such constructor exists, an {@code IllegalArgumentException} is thrown. * * @throws X if {@code get} throws any checked exception except for an {@code ExecutionException} * whose cause is not itself a checked exception diff --git a/guava/src/com/google/common/util/concurrent/FuturesGetChecked.java b/guava/src/com/google/common/util/concurrent/FuturesGetChecked.java index c512d82ee..17e0675b6 100644 --- a/guava/src/com/google/common/util/concurrent/FuturesGetChecked.java +++ b/guava/src/com/google/common/util/concurrent/FuturesGetChecked.java @@ -21,7 +21,6 @@ import static java.util.Arrays.asList; import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Function; import com.google.common.collect.Ordering; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.j2objc.annotations.J2ObjCIncompatible; @@ -225,7 +224,7 @@ final class FuturesGetChecked { try { Exception unused = newWithCause(exceptionClass, new Exception()); return true; - } catch (RuntimeException | Error e) { + } catch (Throwable t) { // sneaky checked exception return false; } } @@ -234,7 +233,7 @@ final class FuturesGetChecked { // getConstructors() guarantees this as long as we don't modify the array. @SuppressWarnings({"unchecked", "rawtypes"}) List<Constructor<X>> constructors = (List) Arrays.asList(exceptionClass.getConstructors()); - for (Constructor<X> constructor : preferringStrings(constructors)) { + for (Constructor<X> constructor : preferringStringsThenThrowables(constructors)) { X instance = newFromConstructor(constructor, cause); if (instance != null) { if (instance.getCause() == null) { @@ -250,17 +249,22 @@ final class FuturesGetChecked { cause); } - private static <X extends Exception> List<Constructor<X>> preferringStrings( + private static <X extends Exception> List<Constructor<X>> preferringStringsThenThrowables( List<Constructor<X>> constructors) { - return WITH_STRING_PARAM_FIRST.sortedCopy(constructors); + return WITH_STRING_PARAM_THEN_WITH_THROWABLE_PARAM.sortedCopy(constructors); } - private static final Ordering<Constructor<?>> WITH_STRING_PARAM_FIRST = + // TODO: b/296487962 - Consider defining a total order over constructors. + private static final Ordering<List<Class<?>>> ORDERING_BY_CONSTRUCTOR_PARAMETER_LIST = Ordering.natural() - .onResultOf( - (Function<Constructor<?>, Boolean>) - input -> asList(input.getParameterTypes()).contains(String.class)) + .onResultOf((List<Class<?>> params) -> params.contains(String.class)) + .compound( + Ordering.natural() + .onResultOf((List<Class<?>> params) -> params.contains(Throwable.class))) .reverse(); + private static final Ordering<Constructor<?>> WITH_STRING_PARAM_THEN_WITH_THROWABLE_PARAM = + ORDERING_BY_CONSTRUCTOR_PARAMETER_LIST.onResultOf( + constructor -> asList(constructor.getParameterTypes())); @CheckForNull private static <X> X newFromConstructor(Constructor<X> constructor, Throwable cause) { diff --git a/guava/src/com/google/common/util/concurrent/ImmediateFuture.java b/guava/src/com/google/common/util/concurrent/ImmediateFuture.java index f09816c4e..62ae63eaa 100644 --- a/guava/src/com/google/common/util/concurrent/ImmediateFuture.java +++ b/guava/src/com/google/common/util/concurrent/ImmediateFuture.java @@ -22,7 +22,6 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.CheckForNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -33,7 +32,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; class ImmediateFuture<V extends @Nullable Object> implements ListenableFuture<V> { static final ListenableFuture<?> NULL = new ImmediateFuture<@Nullable Object>(null); - private static final Logger log = Logger.getLogger(ImmediateFuture.class.getName()); + private static final LazyLogger log = new LazyLogger(ImmediateFuture.class); @ParametricNullness private final V value; @@ -42,18 +41,23 @@ class ImmediateFuture<V extends @Nullable Object> implements ListenableFuture<V> } @Override + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception public void addListener(Runnable listener, Executor executor) { checkNotNull(listener, "Runnable was null."); checkNotNull(executor, "Executor was null."); try { executor.execute(listener); - } catch (RuntimeException e) { + } catch (Exception e) { // sneaky checked exception // ListenableFuture's contract is that it will not throw unchecked exceptions, so log the bad // runnable and/or executor and swallow it. - log.log( - Level.SEVERE, - "RuntimeException while executing runnable " + listener + " with executor " + executor, - e); + log.get() + .log( + Level.SEVERE, + "RuntimeException while executing runnable " + + listener + + " with executor " + + executor, + e); } } diff --git a/guava/src/com/google/common/util/concurrent/InterruptibleTask.java b/guava/src/com/google/common/util/concurrent/InterruptibleTask.java index 6f33c5032..effa8ef59 100644 --- a/guava/src/com/google/common/util/concurrent/InterruptibleTask.java +++ b/guava/src/com/google/common/util/concurrent/InterruptibleTask.java @@ -23,6 +23,7 @@ import com.google.j2objc.annotations.ReflectionSupport; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.AbstractOwnableSynchronizer; import java.util.concurrent.locks.LockSupport; +import javax.annotation.CheckForNull; import org.checkerframework.checker.nullness.qual.Nullable; @GwtCompatible(emulated = true) @@ -234,6 +235,7 @@ abstract class InterruptibleTask<T extends @Nullable Object> } @VisibleForTesting + @CheckForNull Thread getOwner() { return super.getExclusiveOwnerThread(); } diff --git a/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java b/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java index 33403c978..eb3a24707 100644 --- a/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java +++ b/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java @@ -19,7 +19,6 @@ import static com.google.common.util.concurrent.Uninterruptibles.getUninterrupti import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -162,10 +161,11 @@ public final class JdkFutureAdapters { * to return a proper ListenableFuture instead of using listenInPoolThread. */ getUninterruptibly(delegate); - } catch (ExecutionException | RuntimeException | Error e) { - // (including CancellationException) + } catch (Throwable t) { + // (including CancellationException and sneaky checked exception) // The task is presumably done, run the listeners. - // TODO(cpovirk): Do *something* in case of Error (and maybe RuntimeException)? + // TODO(cpovirk): Do *something* in case of Error (and maybe + // non-CancellationException, non-ExecutionException exceptions)? } executionList.execute(); }); diff --git a/guava/src/com/google/common/util/concurrent/LazyLogger.java b/guava/src/com/google/common/util/concurrent/LazyLogger.java new file mode 100644 index 000000000..9ae0f784e --- /dev/null +++ b/guava/src/com/google/common/util/concurrent/LazyLogger.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2023 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.util.concurrent; + +import com.google.common.annotations.GwtCompatible; +import java.util.logging.Logger; +import org.checkerframework.checker.nullness.qual.Nullable; + +/** A holder for a {@link Logger} that is initialized only when requested. */ +@GwtCompatible +@ElementTypesAreNonnullByDefault +final class LazyLogger { + private final String loggerName; + private volatile @Nullable Logger logger; + + LazyLogger(Class<?> ownerOfLogger) { + this.loggerName = ownerOfLogger.getName(); + } + + Logger get() { + /* + * We use double-checked locking. We could the try racy single-check idiom, but that would + * depend on Logger not contain mutable state. + * + * We could use Suppliers.memoizingSupplier here, but I micro-optimized to this implementation + * to avoid the extra class for the lambda (and maybe more for memoizingSupplier itself) and the + * indirection. + * + * One thing to *avoid* is a change to make each Logger user use memoizingSupplier directly: + * That may introduce an extra class for each lambda (currently a dozen). + */ + Logger local = logger; + if (local != null) { + return local; + } + synchronized (this) { + local = logger; + if (local != null) { + return local; + } + return logger = Logger.getLogger(loggerName); + } + } +} diff --git a/guava/src/com/google/common/util/concurrent/ListenerCallQueue.java b/guava/src/com/google/common/util/concurrent/ListenerCallQueue.java index 4ef7ed36c..e6284e1c7 100644 --- a/guava/src/com/google/common/util/concurrent/ListenerCallQueue.java +++ b/guava/src/com/google/common/util/concurrent/ListenerCallQueue.java @@ -27,7 +27,6 @@ import java.util.List; import java.util.Queue; import java.util.concurrent.Executor; import java.util.logging.Level; -import java.util.logging.Logger; /** * A list of listeners for implementing a concurrency friendly observable object. @@ -58,7 +57,7 @@ import java.util.logging.Logger; @ElementTypesAreNonnullByDefault final class ListenerCallQueue<L> { // TODO(cpovirk): consider using the logger associated with listener.getClass(). - private static final Logger logger = Logger.getLogger(ListenerCallQueue.class.getName()); + private static final LazyLogger logger = new LazyLogger(ListenerCallQueue.class); // TODO(chrisn): promote AppendOnlyCollection for use here. private final List<PerListenerQueue<L>> listeners = @@ -159,6 +158,7 @@ final class ListenerCallQueue<L> { * Dispatches all listeners {@linkplain #enqueue enqueued} prior to this call, serially and in * order. */ + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception void dispatch() { boolean scheduleEventRunner = false; synchronized (this) { @@ -170,22 +170,25 @@ final class ListenerCallQueue<L> { if (scheduleEventRunner) { try { executor.execute(this); - } catch (RuntimeException e) { + } catch (Exception e) { // sneaky checked exception // reset state in case of an error so that later dispatch calls will actually do something synchronized (this) { isThreadScheduled = false; } // Log it and keep going. - logger.log( - Level.SEVERE, - "Exception while running callbacks for " + listener + " on " + executor, - e); + logger + .get() + .log( + Level.SEVERE, + "Exception while running callbacks for " + listener + " on " + executor, + e); throw e; } } } @Override + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception public void run() { boolean stillRunning = true; try { @@ -206,12 +209,14 @@ final class ListenerCallQueue<L> { // Always run while _not_ holding the lock, to avoid deadlocks. try { nextToRun.call(listener); - } catch (RuntimeException e) { + } catch (Exception e) { // sneaky checked exception // Log it and keep going. - logger.log( - Level.SEVERE, - "Exception while executing callback: " + listener + " " + nextLabel, - e); + logger + .get() + .log( + Level.SEVERE, + "Exception while executing callback: " + listener + " " + nextLabel, + e); } } } finally { diff --git a/guava/src/com/google/common/util/concurrent/Monitor.java b/guava/src/com/google/common/util/concurrent/Monitor.java index 2ed31eda4..1abbc6405 100644 --- a/guava/src/com/google/common/util/concurrent/Monitor.java +++ b/guava/src/com/google/common/util/concurrent/Monitor.java @@ -1123,7 +1123,8 @@ public final class Monitor { private boolean isSatisfied(Guard guard) { try { return guard.isSatisfied(); - } catch (RuntimeException | Error throwable) { + } catch (Throwable throwable) { + // Any Exception is either a RuntimeException or sneaky checked exception. signalAllWaiters(); throw throwable; } diff --git a/guava/src/com/google/common/util/concurrent/MoreExecutors.java b/guava/src/com/google/common/util/concurrent/MoreExecutors.java index ea3536957..46536fbe7 100644 --- a/guava/src/com/google/common/util/concurrent/MoreExecutors.java +++ b/guava/src/com/google/common/util/concurrent/MoreExecutors.java @@ -739,7 +739,8 @@ public final class MoreExecutors { public void run() { try { delegate.run(); - } catch (RuntimeException | Error t) { + } catch (Throwable t) { + // Any Exception is either a RuntimeException or sneaky checked exception. setException(t); throw t; } @@ -784,7 +785,10 @@ public final class MoreExecutors { * An implementation of {@link ExecutorService#invokeAny} for {@link ListeningExecutorService} * implementations. */ - @SuppressWarnings("GoodTime") // should accept a java.time.Duration + @SuppressWarnings({ + "GoodTime", // should accept a java.time.Duration + "CatchingUnchecked", // sneaky checked exception + }) @J2ktIncompatible @GwtIncompatible @ParametricNullness @@ -847,7 +851,9 @@ public final class MoreExecutors { return f.get(); } catch (ExecutionException eex) { ee = eex; - } catch (RuntimeException rex) { + } catch (InterruptedException iex) { + throw iex; + } catch (Exception rex) { // sneaky checked exception ee = new ExecutionException(rex); } } diff --git a/guava/src/com/google/common/util/concurrent/SequentialExecutor.java b/guava/src/com/google/common/util/concurrent/SequentialExecutor.java index c842d7e07..ebc33178d 100644 --- a/guava/src/com/google/common/util/concurrent/SequentialExecutor.java +++ b/guava/src/com/google/common/util/concurrent/SequentialExecutor.java @@ -31,7 +31,6 @@ import java.util.Deque; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.CheckForNull; /** @@ -52,7 +51,7 @@ import javax.annotation.CheckForNull; @GwtIncompatible @ElementTypesAreNonnullByDefault final class SequentialExecutor implements Executor { - private static final Logger log = Logger.getLogger(SequentialExecutor.class.getName()); + private static final LazyLogger log = new LazyLogger(SequentialExecutor.class); enum WorkerRunningState { /** Runnable is not running and not queued for execution */ @@ -136,7 +135,8 @@ final class SequentialExecutor implements Executor { try { executor.execute(worker); - } catch (RuntimeException | Error t) { + } catch (Throwable t) { + // Any Exception is either a RuntimeException or sneaky checked exception. synchronized (queue) { boolean removed = (workerRunningState == IDLE || workerRunningState == QUEUING) @@ -202,6 +202,7 @@ final class SequentialExecutor implements Executor { * will still be present. If the composed Executor is an ExecutorService, it can respond to * shutdown() by returning tasks queued on that Thread after {@link #worker} drains the queue. */ + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception private void workOnQueue() { boolean interruptedDuringTask = false; boolean hasSetRunning = false; @@ -235,8 +236,8 @@ final class SequentialExecutor implements Executor { interruptedDuringTask |= Thread.interrupted(); try { task.run(); - } catch (RuntimeException e) { - log.log(Level.SEVERE, "Exception while executing runnable " + task, e); + } catch (Exception e) { // sneaky checked exception + log.get().log(Level.SEVERE, "Exception while executing runnable " + task, e); } finally { task = null; } diff --git a/guava/src/com/google/common/util/concurrent/ServiceManager.java b/guava/src/com/google/common/util/concurrent/ServiceManager.java index 42652c967..0bda0afec 100644 --- a/guava/src/com/google/common/util/concurrent/ServiceManager.java +++ b/guava/src/com/google/common/util/concurrent/ServiceManager.java @@ -65,7 +65,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.logging.Level; -import java.util.logging.Logger; /** * A manager for monitoring and controlling a set of {@linkplain Service services}. This class @@ -125,7 +124,7 @@ import java.util.logging.Logger; @GwtIncompatible @ElementTypesAreNonnullByDefault public final class ServiceManager implements ServiceManagerBridge { - private static final Logger logger = Logger.getLogger(ServiceManager.class.getName()); + private static final LazyLogger logger = new LazyLogger(ServiceManager.class); private static final ListenerCallQueue.Event<Listener> HEALTHY_EVENT = new ListenerCallQueue.Event<Listener>() { @Override @@ -208,10 +207,13 @@ public final class ServiceManager implements ServiceManagerBridge { if (copy.isEmpty()) { // Having no services causes the manager to behave strangely. Notably, listeners are never // fired. To avoid this we substitute a placeholder service. - logger.log( - Level.WARNING, - "ServiceManager configured with no services. Is your application configured properly?", - new EmptyServiceManagerWarning()); + logger + .get() + .log( + Level.WARNING, + "ServiceManager configured with no services. Is your application configured" + + " properly?", + new EmptyServiceManagerWarning()); copy = ImmutableList.<Service>of(new NoOpService()); } this.state = new ServiceManagerState(copy); @@ -278,7 +280,7 @@ public final class ServiceManager implements ServiceManagerBridge { // service or listener). Our contract says it is safe to call this method if // all services were NEW when it was called, and this has already been verified above, so we // don't propagate the exception. - logger.log(Level.WARNING, "Unable to start Service " + service, e); + logger.get().log(Level.WARNING, "Unable to start Service " + service, e); } } return this; @@ -706,7 +708,7 @@ public final class ServiceManager implements ServiceManagerBridge { // N.B. if we miss the STARTING event then we may never record a startup time. stopwatch.stop(); if (!(service instanceof NoOpService)) { - logger.log(Level.FINE, "Started {0} in {1}.", new Object[] {service, stopwatch}); + logger.get().log(Level.FINE, "Started {0} in {1}.", new Object[] {service, stopwatch}); } } // Queue our listeners @@ -798,7 +800,7 @@ public final class ServiceManager implements ServiceManagerBridge { if (state != null) { state.transitionService(service, NEW, STARTING); if (!(service instanceof NoOpService)) { - logger.log(Level.FINE, "Starting {0}.", service); + logger.get().log(Level.FINE, "Starting {0}.", service); } } } @@ -824,10 +826,12 @@ public final class ServiceManager implements ServiceManagerBridge { ServiceManagerState state = this.state.get(); if (state != null) { if (!(service instanceof NoOpService)) { - logger.log( - Level.FINE, - "Service {0} has terminated. Previous state was: {1}", - new Object[] {service, from}); + logger + .get() + .log( + Level.FINE, + "Service {0} has terminated. Previous state was: {1}", + new Object[] {service, from}); } state.transitionService(service, from, TERMINATED); } @@ -846,10 +850,12 @@ public final class ServiceManager implements ServiceManagerBridge { */ log &= from != State.STARTING; if (log) { - logger.log( - Level.SEVERE, - "Service " + service + " has failed in the " + from + " state.", - failure); + logger + .get() + .log( + Level.SEVERE, + "Service " + service + " has failed in the " + from + " state.", + failure); } state.transitionService(service, from, FAILED); } diff --git a/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java b/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java index 1dc1094d4..9890c89d6 100644 --- a/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java +++ b/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java @@ -21,7 +21,6 @@ import com.google.common.annotations.J2ktIncompatible; import com.google.common.annotations.VisibleForTesting; import java.lang.Thread.UncaughtExceptionHandler; import java.util.Locale; -import java.util.logging.Logger; /** * Factories for {@link UncaughtExceptionHandler} instances. @@ -57,7 +56,7 @@ public final class UncaughtExceptionHandlers { @VisibleForTesting static final class Exiter implements UncaughtExceptionHandler { - private static final Logger logger = Logger.getLogger(Exiter.class.getName()); + private static final LazyLogger logger = new LazyLogger(Exiter.class); private final Runtime runtime; @@ -68,9 +67,13 @@ public final class UncaughtExceptionHandlers { @Override public void uncaughtException(Thread t, Throwable e) { try { - logger.log( - SEVERE, String.format(Locale.ROOT, "Caught an exception in %s. Shutting down.", t), e); - } catch (RuntimeException | Error errorInLogging) { + logger + .get() + .log( + SEVERE, + String.format(Locale.ROOT, "Caught an exception in %s. Shutting down.", t), + e); + } catch (Throwable errorInLogging) { // sneaky checked exception // If logging fails, e.g. due to missing memory, at least try to log the // message and the cause for the failed logging. System.err.println(e.getMessage()); |