| package org.checkerframework.framework.util; |
| |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.Set; |
| import java.util.TreeSet; |
| import javax.lang.model.element.AnnotationMirror; |
| import org.checkerframework.javacutil.AnnotationUtils; |
| |
| /** |
| * The Set interface defines many methods with respect to the equals method. This implementation of |
| * Set violates those specifications, but fulfills the same property using {@link |
| * AnnotationUtils#areSame} rather than equals. |
| * |
| * <p>For example, the specification for the contains(Object o) method says: "returns true if and |
| * only if this collection contains at least one element e such that (o == null ? e == null : |
| * o.equals(e))." The specification for {@link AnnotationMirrorSet#contains} is "returns true if and |
| * only if this collection contains at least one element e such that (o == null ? e == null : |
| * AnnotationUtils.areSame(o, e))". |
| * |
| * <p>AnnotationMirror is an interface and not all implementing classes provide a correct equals |
| * method; therefore, the existing implementations of Set cannot be used. |
| */ |
| public class AnnotationMirrorSet implements Set<AnnotationMirror> { |
| |
| /** Backing set. */ |
| private Set<AnnotationMirror> shadowSet = |
| new TreeSet<>(AnnotationUtils::compareAnnotationMirrors); |
| |
| /** Default constructor. */ |
| public AnnotationMirrorSet() {} |
| |
| public AnnotationMirrorSet(Collection<? extends AnnotationMirror> values) { |
| this(); |
| this.addAll(values); |
| } |
| |
| @Override |
| public int size() { |
| return shadowSet.size(); |
| } |
| |
| @Override |
| public boolean isEmpty() { |
| return shadowSet.isEmpty(); |
| } |
| |
| @Override |
| public boolean contains(Object o) { |
| return o instanceof AnnotationMirror |
| && AnnotationUtils.containsSame(shadowSet, (AnnotationMirror) o); |
| } |
| |
| @Override |
| public Iterator<AnnotationMirror> iterator() { |
| return shadowSet.iterator(); |
| } |
| |
| @Override |
| public Object[] toArray() { |
| return shadowSet.toArray(); |
| } |
| |
| @Override |
| public <T> T[] toArray(T[] a) { |
| return shadowSet.toArray(a); |
| } |
| |
| @Override |
| public boolean add(AnnotationMirror annotationMirror) { |
| if (contains(annotationMirror)) { |
| return false; |
| } |
| shadowSet.add(annotationMirror); |
| return true; |
| } |
| |
| @Override |
| public boolean remove(Object o) { |
| if (o instanceof AnnotationMirror) { |
| AnnotationMirror found = AnnotationUtils.getSame(shadowSet, (AnnotationMirror) o); |
| return found != null && shadowSet.remove(found); |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean containsAll(Collection<?> c) { |
| for (Object o : c) { |
| if (!contains(o)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public boolean addAll(Collection<? extends AnnotationMirror> c) { |
| boolean result = true; |
| for (AnnotationMirror a : c) { |
| if (!add(a)) { |
| result = false; |
| } |
| } |
| return result; |
| } |
| |
| @Override |
| public boolean retainAll(Collection<?> c) { |
| Set<AnnotationMirror> newSet = new TreeSet<>(AnnotationUtils::compareAnnotationMirrors); |
| for (Object o : c) { |
| if (contains(o)) { |
| newSet.add((AnnotationMirror) o); |
| } |
| } |
| if (newSet.size() != shadowSet.size()) { |
| shadowSet = newSet; |
| return true; |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean removeAll(Collection<?> c) { |
| boolean result = true; |
| for (Object a : c) { |
| if (!remove(a)) { |
| result = false; |
| } |
| } |
| return result; |
| } |
| |
| @Override |
| public void clear() { |
| shadowSet.clear(); |
| } |
| |
| /** |
| * Returns a new {@link AnnotationMirrorSet} that contains {@code value}. |
| * |
| * @param value AnnotationMirror to put in the set |
| * @return a new {@link AnnotationMirrorSet} that contains {@code value} |
| */ |
| public static AnnotationMirrorSet singleElementSet(AnnotationMirror value) { |
| AnnotationMirrorSet newSet = new AnnotationMirrorSet(); |
| newSet.add(value); |
| return newSet; |
| } |
| |
| @Override |
| public String toString() { |
| return shadowSet.toString(); |
| } |
| } |