Skip to content
This repository was archived by the owner on Oct 16, 2024. It is now read-only.

Commit 43c5581

Browse files
authored
Merge pull request #433 from thespags/master
2 parents e19d636 + 618229d commit 43c5581

File tree

5 files changed

+126
-12
lines changed

5 files changed

+126
-12
lines changed

src/main/java/org/inferred/freebuilder/processor/excerpt/CheckedBiMap.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,11 @@ public void addTo(SourceBuilder code) {
4848
.addLine(" }")
4949
.addLine("")
5050
.addLine(" @Override public V put(K key, V value) {")
51+
.addLine(" K oldKey = biMap.inverse().get(value);")
5152
.addLine(" %s.checkArgument(", Preconditions.class)
52-
.addLine(" !biMap.containsValue(value), \"value already present: %%s\", value);")
53+
.addLine(" oldKey == null || %s.equals(oldKey, key),"
54+
+ " \"value already present: %%s\", value);",
55+
Objects.class)
5356
.addLine(" V oldValue = biMap.get(key);")
5457
.addLine(" forcePut.accept(key, value);")
5558
.addLine(" return oldValue;")
@@ -126,9 +129,12 @@ public void addTo(SourceBuilder code) {
126129
.addLine(" }")
127130
.addLine("")
128131
.addLine(" @Override public V setValue(V value) {")
132+
.addLine(" K oldKey = biMap.inverse().get(value);")
129133
.addLine(" %s.checkArgument(", Preconditions.class)
130-
.addLine(" !biMap.containsValue(value), \"value already present: %%s\", value);")
131-
.addLine(" V oldValue = value;")
134+
.addLine(" oldKey == null || %s.equals(oldKey, key),"
135+
+ " \"value already present: %%s\", value);",
136+
Objects.class)
137+
.addLine(" V oldValue = this.value;")
132138
.addLine(" this.value = %s.requireNonNull(value);", Objects.class)
133139
.addLine(" forcePut.accept(key, value);")
134140
.addLine(" return oldValue;")

src/main/java/org/inferred/freebuilder/processor/property/BiMapProperty.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ public Optional<BiMapProperty> create(Config config) {
8686
config, unboxedKeyType.orElse(keyType), unboxedValueType.orElse(valueType));
8787
boolean overridesForcePutMethod = hasForcePutMethodOverride(
8888
config, unboxedKeyType.orElse(keyType), unboxedValueType.orElse(valueType));
89-
89+
9090
if (putMethodOverride.isPresent() && !overridesForcePutMethod) {
9191
config.getEnvironment().getMessager().printMessage(
92-
Kind.ERROR,
92+
Kind.ERROR,
9393
"Overriding "
9494
+ putMethod(property)
9595
+ " will not correctly validate all inputs. Please override "
@@ -226,9 +226,11 @@ private void addPut(SourceBuilder code) {
226226
putMethod(property),
227227
unboxedKeyType.orElse(keyType),
228228
unboxedValueType.orElse(valueType));
229-
code.addLine(" %s.checkArgument(", Preconditions.class)
230-
.addLine(" !%s.containsValue(value), \"value already present: %%s\", value);",
231-
property.getField())
229+
code.addLine(" %s oldKey = %s.inverse().get(value);", keyType, property.getField())
230+
.addLine(" %s.checkArgument(", Preconditions.class)
231+
.addLine(" oldKey == null || %s.equals(oldKey, key),"
232+
+ " \"value already present: %%s\", value);",
233+
Objects.class)
232234
.addLine(" %s(key, value);", forcePutMethod(property))
233235
.addLine(" return (%s) this;", datatype.getBuilder())
234236
.addLine("}");

src/test/java/org/inferred/freebuilder/processor/property/BiMapMutateMethodTest.java

+77
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,22 @@ public void putReplacesDuplicateKey() {
171171
.runTest();
172172
}
173173

174+
@Test
175+
public void putReplacesDuplicateKeyAndValue() {
176+
behaviorTester
177+
.with(bimapPropertyType)
178+
.with(testBuilder()
179+
.addLine("DataType value = new DataType.Builder()")
180+
.addLine(" .putItems(%s, %s)", keys.example(0), values.example(0))
181+
.addLine(" .mutateItems(items -> items.put(%s, %s))",
182+
keys.example(0), values.example(0))
183+
.addLine(" .build();")
184+
.addLine("assertThat(value.%s).isEqualTo(%s);",
185+
convention.get(), exampleBiMap(0, 0))
186+
.build())
187+
.runTest();
188+
}
189+
174190
@Test
175191
public void putRejectsDuplicateValue() {
176192
thrown.expect(IllegalArgumentException.class);
@@ -234,6 +250,22 @@ public void inversePutReplacesDuplicateValue() {
234250
.runTest();
235251
}
236252

253+
@Test
254+
public void inversePutReplacesDuplicateKeyAndValue() {
255+
behaviorTester
256+
.with(bimapPropertyType)
257+
.with(testBuilder()
258+
.addLine("DataType value = new DataType.Builder()")
259+
.addLine(" .putItems(%s, %s)", keys.example(0), values.example(0))
260+
.addLine(" .mutateItems(items -> items.inverse().put(%s, %s))",
261+
values.example(0), keys.example(0))
262+
.addLine(" .build();")
263+
.addLine("assertThat(value.%s).isEqualTo(%s);",
264+
convention.get(), exampleBiMap(0, 0))
265+
.build())
266+
.runTest();
267+
}
268+
237269
@Test
238270
public void inversePutRejectsDuplicateKey() {
239271
thrown.expect(IllegalArgumentException.class);
@@ -659,6 +691,19 @@ public void callSetValueOnEntryChecksDuplicateValue() {
659691
.runTest();
660692
}
661693

694+
@Test
695+
public void callSetValueOnEntryAllowsDuplicateKeyAndValue() {
696+
behaviorTester
697+
.with(bimapPropertyType)
698+
.with(testBuilder()
699+
.addLine("new DataType.Builder()")
700+
.addLine(" .putItems(%s, %s)", keys.example(0), values.example(0))
701+
.addLine(" .mutateItems(items -> items.entrySet().iterator().next().setValue(%s));",
702+
values.example(0))
703+
.build())
704+
.runTest();
705+
}
706+
662707
@Test
663708
public void callSetValueOnEntryModifiesUnderlyingProperty() {
664709
behaviorTester
@@ -674,6 +719,24 @@ public void callSetValueOnEntryModifiesUnderlyingProperty() {
674719
.runTest();
675720
}
676721

722+
@Test
723+
public void callSetValueReturnsOldValue() {
724+
behaviorTester
725+
.with(bimapPropertyType)
726+
.with(testBuilder()
727+
.addLine("new DataType.Builder()")
728+
.addLine(" .putItems(%s, %s)", keys.example(0), values.example(0))
729+
.addLine(" .mutateItems(items -> {")
730+
.addLine(" Iterator<Map.Entry<%s, %s>> i = items.entrySet().iterator();",
731+
keys.type(), values.type())
732+
.addLine(" Map.Entry<%s, %s> entry = i.next();", keys.type(), values.type())
733+
.addLine(" %s oldValue = entry.setValue(%s);", values.type(), values.example(2))
734+
.addLine(" assertThat(oldValue).isEqualTo(%s);", values.example(0))
735+
.addLine(" });")
736+
.build())
737+
.runTest();
738+
}
739+
677740
@Test
678741
public void callSetValueOnInverseEntryChecksArguments() {
679742
if (checked) {
@@ -709,6 +772,20 @@ public void callSetValueOnInverseEntryChecksDuplicateValue() {
709772
.runTest();
710773
}
711774

775+
@Test
776+
public void callSetValueOnInverseEntryAllowsDuplicateKeyAndValue() {
777+
behaviorTester
778+
.with(bimapPropertyType)
779+
.with(testBuilder()
780+
.addLine("new DataType.Builder()")
781+
.addLine(" .putItems(%s, %s)", keys.example(0), values.example(0))
782+
.addLine(" .mutateItems(items -> items")
783+
.addLine(" .inverse().entrySet().iterator().next().setValue(%s));",
784+
keys.example(0))
785+
.build())
786+
.runTest();
787+
}
788+
712789
@Test
713790
public void callSetValueOnInverseEntryModifiesUnderlyingProperty() {
714791
behaviorTester

src/test/java/org/inferred/freebuilder/processor/property/BiMapPropertyTest.java

+30-3
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ public void testPut_nullValue() {
178178
}
179179

180180
@Test
181-
public void testPut_duplicate() {
181+
public void testPut_duplicateKey() {
182182
behaviorTester
183183
.with(biMapPropertyType)
184184
.with(testBuilder()
@@ -191,6 +191,33 @@ public void testPut_duplicate() {
191191
.runTest();
192192
}
193193

194+
@Test
195+
public void testPut_duplicateValue() {
196+
thrown.expect(IllegalArgumentException.class);
197+
behaviorTester
198+
.with(biMapPropertyType)
199+
.with(testBuilder()
200+
.addLine("new DataType.Builder()")
201+
.addLine(" .putItems(%s, %s)", keys.example(0), values.example(0))
202+
.addLine(" .putItems(%s, %s);", keys.example(1), values.example(0))
203+
.build())
204+
.runTest();
205+
}
206+
207+
@Test
208+
public void testPut_duplicateKeyAndValue() {
209+
behaviorTester
210+
.with(biMapPropertyType)
211+
.with(testBuilder()
212+
.addLine("DataType value = new DataType.Builder()")
213+
.addLine(" .putItems(%s, %s)", keys.example(0), values.example(0))
214+
.addLine(" .putItems(%s, %s)", keys.example(0), values.example(0))
215+
.addLine(" .build();")
216+
.addLine("assertThat(value.%s).isEqualTo(%s);", convention.get(), exampleMap(0, 0))
217+
.build())
218+
.runTest();
219+
}
220+
194221
@Test
195222
public void testForcePut() {
196223
behaviorTester
@@ -237,9 +264,9 @@ public void testForcePut_duplicate() {
237264
.with(testBuilder()
238265
.addLine("DataType value = new DataType.Builder()")
239266
.addLine(" .forcePutItems(%s, %s)", keys.example(0), values.example(0))
240-
.addLine(" .forcePutItems(%s, %s)", keys.example(0), values.example(1))
267+
.addLine(" .forcePutItems(%s, %s)", keys.example(1), values.example(0))
241268
.addLine(" .build();")
242-
.addLine("assertThat(value.%s).isEqualTo(%s);", convention.get(), exampleMap(0, 1))
269+
.addLine("assertThat(value.%s).isEqualTo(%s);", convention.get(), exampleMap(1, 0))
243270
.build())
244271
.runTest();
245272
}

src/test/java/org/inferred/freebuilder/processor/property/BiMapSourceTest.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ public void test_guava() {
9090
" * @throws NullPointerException if {@code value} is null",
9191
" */",
9292
" public Person.Builder putName(int key, String value) {",
93-
" Preconditions.checkArgument(!name.containsValue(value), \"value already present: %s\", value);",
93+
" Integer oldKey = name.inverse().get(value);",
94+
" Preconditions.checkArgument(",
95+
" oldKey == null || Objects.equals(oldKey, key), \"value already present: %s\", value);",
9496
" forcePutName(key, value);",
9597
" return (Person.Builder) this;",
9698
" }",

0 commit comments

Comments
 (0)