From e13d5177c52ae80d785de0aad8f9e7ad1bdd0355 Mon Sep 17 00:00:00 2001 From: Chris Povirk Date: Thu, 28 Apr 2022 14:56:56 -0400 Subject: [PATCH] Improve annotations on some java.util.concurrent collections. --- .../util/concurrent/ArrayBlockingQueue.java | 8 +++-- .../util/concurrent/CopyOnWriteArrayList.java | 10 +++--- .../util/concurrent/CopyOnWriteArraySet.java | 6 ++-- .../util/concurrent/LinkedBlockingDeque.java | 32 ++++++++++--------- .../util/concurrent/LinkedBlockingQueue.java | 14 ++++---- .../concurrent/PriorityBlockingQueue.java | 14 ++++---- 6 files changed, 48 insertions(+), 36 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java index 57c5291c9b9..d6796d57c8a 100644 --- a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java @@ -39,6 +39,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.framework.qual.AnnotatedFor; import java.lang.ref.WeakReference; import java.util.AbstractQueue; @@ -88,7 +89,8 @@ * @author Doug Lea * @param the type of elements held in this queue */ -public class ArrayBlockingQueue extends AbstractQueue +@AnnotatedFor({"nullness"}) +public class ArrayBlockingQueue extends AbstractQueue implements BlockingQueue, java.io.Serializable { /* @@ -1479,7 +1481,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1487,7 +1489,7 @@ public boolean removeAll(Collection c) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean retainAll(Collection c) { + public boolean retainAll(Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java index 39d2b7ec60c..d9e3bd51546 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -40,6 +40,7 @@ import org.checkerframework.checker.nullness.qual.PolyNull; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; +import org.checkerframework.framework.qual.AnnotatedFor; import java.lang.invoke.VarHandle; import java.lang.reflect.Field; @@ -97,6 +98,7 @@ * @author Doug Lea * @param the type of elements held in this list */ +@AnnotatedFor({"nullness"}) public class CopyOnWriteArrayList implements List, RandomAccess, Cloneable, java.io.Serializable { private static final long serialVersionUID = 8673264195747942595L; @@ -263,7 +265,7 @@ public int indexOf(@Nullable Object o) { * {@code -1} if the element is not found. * @throws IndexOutOfBoundsException if the specified index is negative */ - public int indexOf(E e, int index) { + public int indexOf(@Nullable E e, int index) { Object[] es = getArray(); return indexOfRange(e, es, index, es.length); } @@ -292,7 +294,7 @@ public int lastIndexOf(@Nullable Object o) { * @throws IndexOutOfBoundsException if the specified index is greater * than or equal to the current size of this list */ - public int lastIndexOf(E e, int index) { + public int lastIndexOf(@Nullable E e, int index) { Object[] es = getArray(); return lastIndexOfRange(e, es, 0, index + 1); } @@ -659,7 +661,7 @@ public boolean containsAll(Collection c) { * or if the specified collection is null * @see #remove(Object) */ - public boolean removeAll(Collection c) { + public boolean removeAll(Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -680,7 +682,7 @@ public boolean removeAll(Collection c) { * or if the specified collection is null * @see #remove(Object) */ - public boolean retainAll(Collection c) { + public boolean retainAll(Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java index 620cc0e9b88..c9431cf78e0 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java @@ -41,6 +41,7 @@ import org.checkerframework.checker.nullness.qual.PolyNull; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; +import org.checkerframework.framework.qual.AnnotatedFor; import java.util.AbstractSet; import java.util.Collection; @@ -102,6 +103,7 @@ * @author Doug Lea * @param the type of elements held in this set */ +@AnnotatedFor({"nullness"}) public class CopyOnWriteArraySet extends AbstractSet implements java.io.Serializable { private static final long serialVersionUID = 5457747651344034263L; @@ -356,7 +358,7 @@ public boolean addAll(Collection c) { * or if the specified collection is null * @see #remove(Object) */ - public boolean removeAll(Collection c) { + public boolean removeAll(Collection c) { return al.removeAll(c); } @@ -379,7 +381,7 @@ public boolean removeAll(Collection c) { * or if the specified collection is null * @see #remove(Object) */ - public boolean retainAll(Collection c) { + public boolean retainAll(Collection c) { return al.retainAll(c); } diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java index 536020fcdde..a9f515fb565 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -39,6 +39,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.framework.qual.AnnotatedFor; import java.util.AbstractQueue; import java.util.Collection; @@ -80,7 +81,8 @@ * @author Doug Lea * @param the type of elements held in this deque */ -public class LinkedBlockingDeque +@AnnotatedFor({"nullness"}) +public class LinkedBlockingDeque extends AbstractQueue implements BlockingDeque, java.io.Serializable { @@ -459,7 +461,7 @@ public E removeLast() { return x; } - public E pollFirst() { + public @Nullable E pollFirst() { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -469,7 +471,7 @@ public E pollFirst() { } } - public E pollLast() { + public @Nullable E pollLast() { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -505,7 +507,7 @@ public E takeLast() throws InterruptedException { } } - public E pollFirst(long timeout, TimeUnit unit) + public @Nullable E pollFirst(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; @@ -523,7 +525,7 @@ public E pollFirst(long timeout, TimeUnit unit) } } - public E pollLast(long timeout, TimeUnit unit) + public @Nullable E pollLast(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; @@ -559,7 +561,7 @@ public E getLast() { return x; } - public E peekFirst() { + public @Nullable E peekFirst() { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -569,7 +571,7 @@ public E peekFirst() { } } - public E peekLast() { + public @Nullable E peekLast() { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -579,7 +581,7 @@ public E peekLast() { } } - public boolean removeFirstOccurrence(Object o) { + public boolean removeFirstOccurrence(@Nullable Object o) { if (o == null) return false; final ReentrantLock lock = this.lock; lock.lock(); @@ -596,7 +598,7 @@ public boolean removeFirstOccurrence(Object o) { } } - public boolean removeLastOccurrence(Object o) { + public boolean removeLastOccurrence(@Nullable Object o) { if (o == null) return false; final ReentrantLock lock = this.lock; lock.lock(); @@ -668,7 +670,7 @@ public E remove() { return removeFirst(); } - public E poll() { + public @Nullable E poll() { return pollFirst(); } @@ -676,7 +678,7 @@ public E take() throws InterruptedException { return takeFirst(); } - public E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { return pollFirst(timeout, unit); } @@ -694,7 +696,7 @@ public E element() { return getFirst(); } - public E peek() { + public @Nullable E peek() { return peekFirst(); } @@ -788,7 +790,7 @@ public E pop() { * @param o element to be removed from this deque, if present * @return {@code true} if this deque changed as a result of the call */ - public boolean remove(Object o) { + public boolean remove(@Nullable Object o) { return removeFirstOccurrence(o); } @@ -1342,7 +1344,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1350,7 +1352,7 @@ public boolean removeAll(Collection c) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean retainAll(Collection c) { + public boolean retainAll(Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java index 7a444647b79..f51a5a4f5c2 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java @@ -39,6 +39,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.framework.qual.AnnotatedFor; import java.util.AbstractQueue; import java.util.Collection; @@ -83,7 +84,8 @@ * @author Doug Lea * @param the type of elements held in this queue */ -public class LinkedBlockingQueue extends AbstractQueue +@AnnotatedFor({"nullness"}) +public class LinkedBlockingQueue extends AbstractQueue implements BlockingQueue, java.io.Serializable { private static final long serialVersionUID = -6903933977591709194L; @@ -450,7 +452,7 @@ public E take() throws InterruptedException { return x; } - public E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { final E x; final int c; long nanos = unit.toNanos(timeout); @@ -475,7 +477,7 @@ public E poll(long timeout, TimeUnit unit) throws InterruptedException { return x; } - public E poll() { + public @Nullable E poll() { final AtomicInteger count = this.count; if (count.get() == 0) return null; @@ -498,7 +500,7 @@ public E poll() { return x; } - public E peek() { + public @Nullable E peek() { final AtomicInteger count = this.count; if (count.get() == 0) return null; @@ -1029,7 +1031,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1037,7 +1039,7 @@ public boolean removeAll(Collection c) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean retainAll(Collection c) { + public boolean retainAll(Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); } diff --git a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java index ff017396e20..ecddf7eab0d 100644 --- a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java @@ -39,6 +39,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.PolyNull; import org.checkerframework.dataflow.qual.Pure; +import org.checkerframework.framework.qual.AnnotatedFor; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; @@ -115,8 +116,9 @@ * @author Doug Lea * @param the type of elements held in this queue */ +@AnnotatedFor({"nullness"}) @SuppressWarnings("unchecked") -public class PriorityBlockingQueue extends AbstractQueue +public class PriorityBlockingQueue extends AbstractQueue implements BlockingQueue, java.io.Serializable { private static final long serialVersionUID = 5595510919245408276L; @@ -533,7 +535,7 @@ public boolean offer(E e, long timeout, TimeUnit unit) { return offer(e); // never need to block } - public E poll() { + public @Nullable E poll() { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -556,7 +558,7 @@ public E take() throws InterruptedException { return result; } - public E poll(long timeout, TimeUnit unit) throws InterruptedException { + public @Nullable E poll(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); @@ -570,7 +572,7 @@ public E poll(long timeout, TimeUnit unit) throws InterruptedException { return result; } - public E peek() { + public @Nullable E peek() { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -1034,7 +1036,7 @@ public boolean removeIf(Predicate filter) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean removeAll(Collection c) { + public boolean removeAll(Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> c.contains(e)); } @@ -1042,7 +1044,7 @@ public boolean removeAll(Collection c) { /** * @throws NullPointerException {@inheritDoc} */ - public boolean retainAll(Collection c) { + public boolean retainAll(Collection c) { Objects.requireNonNull(c); return bulkRemove(e -> !c.contains(e)); }