Skip to content

Commit e4d8aca

Browse files
authored
Introduce DequeRules Refaster rule collection (#1946)
1 parent 7c40619 commit e4d8aca

File tree

8 files changed

+1553
-3
lines changed

8 files changed

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

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: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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 java.util.LinkedList;
7+
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
8+
9+
final class DequeRulesTest implements RefasterRuleCollectionTestCase {
10+
void testDequeAddFirst() {
11+
new ArrayDeque<String>().push("foo");
12+
}
13+
14+
void testDequeAddLast() {
15+
new ArrayDeque<String>().add("foo");
16+
new LinkedList<String>().add("bar");
17+
}
18+
19+
ImmutableSet<String> testDequeRemoveFirst() {
20+
return ImmutableSet.of(new ArrayDeque<String>(0).pop(), new ArrayDeque<String>(1).remove());
21+
}
22+
23+
boolean testDequeOfferLast() {
24+
return new ArrayDeque<String>().offer("foo");
25+
}
26+
27+
String testDequePollFirst() {
28+
return new ArrayDeque<String>().poll();
29+
}
30+
31+
String testDequeGetFirst() {
32+
return new ArrayDeque<String>().element();
33+
}
34+
35+
String testDequePeekFirst() {
36+
return new ArrayDeque<String>().peek();
37+
}
38+
39+
boolean testDequeRemoveFirstOccurrence() {
40+
return new ArrayDeque<>().remove("foo");
41+
}
42+
43+
Iterator<String> testDequeIterator() {
44+
return new ArrayDeque<String>().reversed().descendingIterator();
45+
}
46+
47+
Iterator<String> testDequeDescendingIterator() {
48+
return new ArrayDeque<String>().reversed().iterator();
49+
}
50+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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 java.util.LinkedList;
7+
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
8+
9+
final class DequeRulesTest implements RefasterRuleCollectionTestCase {
10+
void testDequeAddFirst() {
11+
new ArrayDeque<String>().addFirst("foo");
12+
}
13+
14+
void testDequeAddLast() {
15+
new ArrayDeque<String>().addLast("foo");
16+
new LinkedList<String>().add("bar");
17+
}
18+
19+
ImmutableSet<String> testDequeRemoveFirst() {
20+
return ImmutableSet.of(
21+
new ArrayDeque<String>(0).removeFirst(), new ArrayDeque<String>(1).removeFirst());
22+
}
23+
24+
boolean testDequeOfferLast() {
25+
return new ArrayDeque<String>().offerLast("foo");
26+
}
27+
28+
String testDequePollFirst() {
29+
return new ArrayDeque<String>().pollFirst();
30+
}
31+
32+
String testDequeGetFirst() {
33+
return new ArrayDeque<String>().getFirst();
34+
}
35+
36+
String testDequePeekFirst() {
37+
return new ArrayDeque<String>().peekFirst();
38+
}
39+
40+
boolean testDequeRemoveFirstOccurrence() {
41+
return new ArrayDeque<>().removeFirstOccurrence("foo");
42+
}
43+
44+
Iterator<String> testDequeIterator() {
45+
return new ArrayDeque<String>().iterator();
46+
}
47+
48+
Iterator<String> testDequeDescendingIterator() {
49+
return new ArrayDeque<String>().descendingIterator();
50+
}
51+
}

0 commit comments

Comments
 (0)