Skip to content

Commit 0bcc409

Browse files
committed
Introduce DequeRules Refaster rule collection
1 parent 6ea1b7c commit 0bcc409

File tree

4 files changed

+244
-0
lines changed

4 files changed

+244
-0
lines changed
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package tech.picnic.errorprone.refasterrules;
2+
3+
import com.google.errorprone.refaster.Refaster;
4+
import com.google.errorprone.refaster.annotation.AfterTemplate;
5+
import com.google.errorprone.refaster.annotation.BeforeTemplate;
6+
import java.util.Deque;
7+
import java.util.Iterator;
8+
import org.jspecify.annotations.Nullable;
9+
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
10+
11+
/** Refaster rules related to expressions dealing with {@link Deque} instances. */
12+
// XXX: Introduce similar rules for `BlockingDeque`.
13+
@OnlineDocumentation
14+
final class DequeRules {
15+
private DequeRules() {}
16+
17+
/** Prefer {@link Deque#addLast(Object)} over less clear alternatives. */
18+
static final class DequeAddFirst<S, T extends S> {
19+
@BeforeTemplate
20+
void before(Deque<S> deque, T element) {
21+
deque.push(element);
22+
}
23+
24+
@AfterTemplate
25+
void after(Deque<S> deque, T element) {
26+
deque.addFirst(element);
27+
}
28+
}
29+
30+
/** Prefer {@link Deque#addLast(Object)} over less clear alternatives. */
31+
static final class DequeAddLast<S, T extends S> {
32+
@BeforeTemplate
33+
void before(Deque<S> deque, T element) {
34+
deque.add(element);
35+
}
36+
37+
@AfterTemplate
38+
void after(Deque<S> deque, T element) {
39+
deque.addLast(element);
40+
}
41+
}
42+
43+
/** Prefer {@link Deque#removeFirst()} over less clear alternatives. */
44+
static final class DequeRemoveFirst<T> {
45+
@BeforeTemplate
46+
T before(Deque<T> deque) {
47+
return Refaster.anyOf(deque.pop(), deque.remove());
48+
}
49+
50+
@AfterTemplate
51+
T after(Deque<T> deque) {
52+
return deque.removeFirst();
53+
}
54+
}
55+
56+
/** Prefer {@link Deque#offerLast(Object)} over less clear alternatives. */
57+
static final class DequeOfferLast<S, T extends S> {
58+
@BeforeTemplate
59+
boolean before(Deque<S> deque, T element) {
60+
return deque.offer(element);
61+
}
62+
63+
@AfterTemplate
64+
boolean after(Deque<S> deque, T element) {
65+
return deque.offerLast(element);
66+
}
67+
}
68+
69+
/** Prefer {@link Deque#pollFirst()} over less clear alternatives. */
70+
static final class DequePollFirst<T> {
71+
@BeforeTemplate
72+
@Nullable T before(Deque<T> deque) {
73+
return deque.poll();
74+
}
75+
76+
@AfterTemplate
77+
@Nullable T after(Deque<T> deque) {
78+
return deque.pollFirst();
79+
}
80+
}
81+
82+
/** Prefer {@link Deque#pollFirst()} over less clear alternatives. */
83+
static final class DequeGetFirst<T> {
84+
@BeforeTemplate
85+
T before(Deque<T> deque) {
86+
return deque.element();
87+
}
88+
89+
@AfterTemplate
90+
T after(Deque<T> deque) {
91+
return deque.getFirst();
92+
}
93+
}
94+
95+
/** Prefer {@link Deque#peekFirst()} over less clear alternatives. */
96+
static final class DequePeekFirst<T> {
97+
@BeforeTemplate
98+
@Nullable T before(Deque<T> deque) {
99+
return deque.peek();
100+
}
101+
102+
@AfterTemplate
103+
@Nullable T after(Deque<T> deque) {
104+
return deque.peekFirst();
105+
}
106+
}
107+
108+
/** Prefer {@link Deque#removeFirstOccurrence(Object)} over less clear alternatives. */
109+
static final class DequeRemoveFirstOccurrence<S, T extends S> {
110+
@BeforeTemplate
111+
boolean before(Deque<S> deque, T element) {
112+
return deque.remove(element);
113+
}
114+
115+
@AfterTemplate
116+
boolean after(Deque<S> deque, T element) {
117+
return deque.removeFirstOccurrence(element);
118+
}
119+
}
120+
121+
/** Prefer {@link Deque#iterator()} over more contrived alternatives. */
122+
static final class DequeIterator<T> {
123+
@BeforeTemplate
124+
Iterator<T> before(Deque<T> deque) {
125+
return deque.reversed().descendingIterator();
126+
}
127+
128+
@AfterTemplate
129+
Iterator<T> after(Deque<T> deque) {
130+
return deque.iterator();
131+
}
132+
}
133+
134+
/** Prefer {@link Deque#descendingIterator()} over more contrived alternatives. */
135+
static final class DequeDescendingIterator<T> {
136+
@BeforeTemplate
137+
Iterator<T> before(Deque<T> deque) {
138+
return deque.reversed().iterator();
139+
}
140+
141+
@AfterTemplate
142+
Iterator<T> after(Deque<T> deque) {
143+
return deque.descendingIterator();
144+
}
145+
}
146+
}

error-prone-contrib/src/test/java/tech/picnic/errorprone/refasterrules/RefasterRulesTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ final class RefasterRulesTest {
4848
ClassRules.class,
4949
CollectionRules.class,
5050
ComparatorRules.class,
51+
DequeRules.class,
5152
DoubleStreamRules.class,
5253
EqualityRules.class,
5354
FileRules.class,
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package tech.picnic.errorprone.refasterrules;
2+
3+
import com.google.common.collect.ImmutableSet;
4+
import java.util.ArrayDeque;
5+
import java.util.Iterator;
6+
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
7+
8+
final class DequeRulesTest implements RefasterRuleCollectionTestCase {
9+
void testDequeAddFirst() {
10+
new ArrayDeque<String>().push("foo");
11+
}
12+
13+
void testDequeAddLast() {
14+
new ArrayDeque<String>().add("foo");
15+
}
16+
17+
ImmutableSet<String> testDequeRemoveFirst() {
18+
return ImmutableSet.of(new ArrayDeque<String>(0).pop(), new ArrayDeque<String>(1).remove());
19+
}
20+
21+
boolean testDequeOfferLast() {
22+
return new ArrayDeque<String>().offer("foo");
23+
}
24+
25+
String testDequePollFirst() {
26+
return new ArrayDeque<String>().poll();
27+
}
28+
29+
String testDequeGetFirst() {
30+
return new ArrayDeque<String>().element();
31+
}
32+
33+
String testDequePeekFirst() {
34+
return new ArrayDeque<String>().peek();
35+
}
36+
37+
boolean testDequeRemoveFirstOccurrence() {
38+
return new ArrayDeque<>().remove("foo");
39+
}
40+
41+
Iterator<String> testDequeIterator() {
42+
return new ArrayDeque<String>().reversed().descendingIterator();
43+
}
44+
45+
Iterator<String> testDequeDescendingIterator() {
46+
return new ArrayDeque<String>().reversed().iterator();
47+
}
48+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package tech.picnic.errorprone.refasterrules;
2+
3+
import com.google.common.collect.ImmutableSet;
4+
import java.util.ArrayDeque;
5+
import java.util.Iterator;
6+
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
7+
8+
final class DequeRulesTest implements RefasterRuleCollectionTestCase {
9+
void testDequeAddFirst() {
10+
new ArrayDeque<String>().addFirst("foo");
11+
}
12+
13+
void testDequeAddLast() {
14+
new ArrayDeque<String>().addLast("foo");
15+
}
16+
17+
ImmutableSet<String> testDequeRemoveFirst() {
18+
return ImmutableSet.of(
19+
new ArrayDeque<String>(0).removeFirst(), new ArrayDeque<String>(1).removeFirst());
20+
}
21+
22+
boolean testDequeOfferLast() {
23+
return new ArrayDeque<String>().offerLast("foo");
24+
}
25+
26+
String testDequePollFirst() {
27+
return new ArrayDeque<String>().pollFirst();
28+
}
29+
30+
String testDequeGetFirst() {
31+
return new ArrayDeque<String>().getFirst();
32+
}
33+
34+
String testDequePeekFirst() {
35+
return new ArrayDeque<String>().peekFirst();
36+
}
37+
38+
boolean testDequeRemoveFirstOccurrence() {
39+
return new ArrayDeque<>().removeFirstOccurrence("foo");
40+
}
41+
42+
Iterator<String> testDequeIterator() {
43+
return new ArrayDeque<String>().iterator();
44+
}
45+
46+
Iterator<String> testDequeDescendingIterator() {
47+
return new ArrayDeque<String>().descendingIterator();
48+
}
49+
}

0 commit comments

Comments
 (0)