Skip to content

Commit a67dc64

Browse files
claudeArtur-
authored andcommitted
fix: Rename ValueSignal.map to mapMutable to avoid method ambiguity
The original implementation of two-way computed signals introduced an ambiguous overload: WritableSignal.map(getter, setter) and ValueSignal.map(getter, modifier) had the same arity but different functional interface parameter types. Java's type inference could not always disambiguate between SignalSetter (returns parent type) and SignalModifier (returns void) when using method references or lambdas. Renaming ValueSignal's method from map to mapMutable resolves this ambiguity and makes the distinction clear in the API: map() creates immutable value mappings, mapMutable() creates in-place modification mappings. Fixes #23370 https://claude.ai/code/session_019LonZZA33kKDmk7jCgN7cT
1 parent 1305d80 commit a67dc64

File tree

2 files changed

+21
-17
lines changed

2 files changed

+21
-17
lines changed

signals/src/main/java/com/vaadin/signals/local/ValueSignal.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,10 @@ public void modify(ValueModifier<T> modifier) {
317317
* a child value. Writing to the mapped signal uses the modifier function to
318318
* update this signal's value in place.
319319
* <p>
320+
* This method is named differently from
321+
* {@link WritableSignal#map(SignalMapper, SignalSetter)} to avoid ambiguity
322+
* in method overload resolution when using method references or lambdas.
323+
* <p>
320324
* This is useful for mutable bean patterns where the parent object's
321325
* properties are modified directly using setters. For example:
322326
*
@@ -335,7 +339,7 @@ public void modify(ValueModifier<T> modifier) {
335339
* }
336340
*
337341
* ValueSignal&lt;Todo&gt; todoSignal = new ValueSignal&lt;&gt;(new Todo());
338-
* WritableSignal&lt;Boolean&gt; doneSignal = todoSignal.map(
342+
* WritableSignal&lt;Boolean&gt; doneSignal = todoSignal.mapMutable(
339343
* Todo::isDone, Todo::setDone);
340344
*
341345
* checkbox.bindValue(doneSignal); // Two-way binding
@@ -352,7 +356,7 @@ public void modify(ValueModifier<T> modifier) {
352356
* @return a two-way mapped signal using in-place modification, not
353357
* <code>null</code>
354358
*/
355-
public <C> WritableSignal<C> map(SignalMapper<T, C> getter,
359+
public <C> WritableSignal<C> mapMutable(SignalMapper<T, C> getter,
356360
SignalModifier<T, C> modifier) {
357361
return new MappedModifySignal<>(this, getter, modifier);
358362
}

signals/src/test/java/com/vaadin/signals/local/MappedModifySignalTest.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ void map_readValue_returnsMappedValue() {
9090
MutableTodo todo = new MutableTodo("Buy milk", false);
9191
ValueSignal<MutableTodo> todoSignal = new ValueSignal<>(todo);
9292
WritableSignal<Boolean> doneSignal = todoSignal
93-
.map(MutableTodo::isDone, MutableTodo::setDone);
93+
.mapMutable(MutableTodo::isDone, MutableTodo::setDone);
9494

9595
assertFalse(doneSignal.value());
9696

@@ -105,7 +105,7 @@ void map_peek_returnsMappedValue() {
105105
MutableTodo todo = new MutableTodo("Buy milk", false);
106106
ValueSignal<MutableTodo> todoSignal = new ValueSignal<>(todo);
107107
WritableSignal<Boolean> doneSignal = todoSignal
108-
.map(MutableTodo::isDone, MutableTodo::setDone);
108+
.mapMutable(MutableTodo::isDone, MutableTodo::setDone);
109109

110110
assertFalse(doneSignal.peek());
111111
}
@@ -115,7 +115,7 @@ void map_setValue_modifiesParentValueInPlace() {
115115
MutableTodo todo = new MutableTodo("Buy milk", false);
116116
ValueSignal<MutableTodo> todoSignal = new ValueSignal<>(todo);
117117
WritableSignal<Boolean> doneSignal = todoSignal
118-
.map(MutableTodo::isDone, MutableTodo::setDone);
118+
.mapMutable(MutableTodo::isDone, MutableTodo::setDone);
119119

120120
doneSignal.value(true);
121121

@@ -128,7 +128,7 @@ void map_setValue_returnsPreviousValue() {
128128
MutableTodo todo = new MutableTodo("Buy milk", false);
129129
ValueSignal<MutableTodo> todoSignal = new ValueSignal<>(todo);
130130
WritableSignal<Boolean> doneSignal = todoSignal
131-
.map(MutableTodo::isDone, MutableTodo::setDone);
131+
.mapMutable(MutableTodo::isDone, MutableTodo::setDone);
132132

133133
SignalOperation<Boolean> operation = doneSignal.value(true);
134134

@@ -141,7 +141,7 @@ void map_setValuePreservesOtherFields() {
141141
MutableTodo todo = new MutableTodo("Original text", false);
142142
ValueSignal<MutableTodo> todoSignal = new ValueSignal<>(todo);
143143
WritableSignal<Boolean> doneSignal = todoSignal
144-
.map(MutableTodo::isDone, MutableTodo::setDone);
144+
.mapMutable(MutableTodo::isDone, MutableTodo::setDone);
145145

146146
doneSignal.value(true);
147147

@@ -153,7 +153,7 @@ void map_replaceWithExpectedValue_updatesSignal() {
153153
MutableTodo todo = new MutableTodo("Buy milk", false);
154154
ValueSignal<MutableTodo> todoSignal = new ValueSignal<>(todo);
155155
WritableSignal<Boolean> doneSignal = todoSignal
156-
.map(MutableTodo::isDone, MutableTodo::setDone);
156+
.mapMutable(MutableTodo::isDone, MutableTodo::setDone);
157157

158158
SignalOperation<Void> operation = doneSignal.replace(false, true);
159159

@@ -167,7 +167,7 @@ void map_replaceWithUnexpectedValue_fails() {
167167
MutableTodo todo = new MutableTodo("Buy milk", false);
168168
ValueSignal<MutableTodo> todoSignal = new ValueSignal<>(todo);
169169
WritableSignal<Boolean> doneSignal = todoSignal
170-
.map(MutableTodo::isDone, MutableTodo::setDone);
170+
.mapMutable(MutableTodo::isDone, MutableTodo::setDone);
171171

172172
SignalOperation<Void> operation = doneSignal.replace(true, false);
173173

@@ -182,7 +182,7 @@ void map_update_modifiesInPlace() {
182182
ValueSignal<MutablePair<Integer, String>> pairSignal =
183183
new ValueSignal<>(pair);
184184
WritableSignal<Integer> firstSignal = pairSignal
185-
.map(MutablePair::getFirst, MutablePair::setFirst);
185+
.mapMutable(MutablePair::getFirst, MutablePair::setFirst);
186186

187187
CancelableOperation<Integer> operation = firstSignal
188188
.update(value -> value * 2);
@@ -200,7 +200,7 @@ void map_update_preservesOtherFields() {
200200
ValueSignal<MutablePair<Integer, String>> pairSignal =
201201
new ValueSignal<>(pair);
202202
WritableSignal<Integer> firstSignal = pairSignal
203-
.map(MutablePair::getFirst, MutablePair::setFirst);
203+
.mapMutable(MutablePair::getFirst, MutablePair::setFirst);
204204

205205
firstSignal.update(value -> value + 10);
206206

@@ -212,7 +212,7 @@ void map_effectTracking_tracksChanges() {
212212
MutableTodo todo = new MutableTodo("Buy milk", false);
213213
ValueSignal<MutableTodo> todoSignal = new ValueSignal<>(todo);
214214
WritableSignal<Boolean> doneSignal = todoSignal
215-
.map(MutableTodo::isDone, MutableTodo::setDone);
215+
.mapMutable(MutableTodo::isDone, MutableTodo::setDone);
216216

217217
AtomicInteger effectCount = new AtomicInteger();
218218
Signal.effect(() -> {
@@ -231,7 +231,7 @@ void map_asReadonly_createsReadonlyView() {
231231
MutableTodo todo = new MutableTodo("Buy milk", false);
232232
ValueSignal<MutableTodo> todoSignal = new ValueSignal<>(todo);
233233
WritableSignal<Boolean> doneSignal = todoSignal
234-
.map(MutableTodo::isDone, MutableTodo::setDone);
234+
.mapMutable(MutableTodo::isDone, MutableTodo::setDone);
235235
Signal<Boolean> readonlySignal = doneSignal.asReadonly();
236236

237237
assertFalse(readonlySignal instanceof WritableSignal);
@@ -245,7 +245,7 @@ void map_stringField_works() {
245245
MutableTodo todo = new MutableTodo("Buy milk", false);
246246
ValueSignal<MutableTodo> todoSignal = new ValueSignal<>(todo);
247247
WritableSignal<String> textSignal = todoSignal
248-
.map(MutableTodo::getText, MutableTodo::setText);
248+
.mapMutable(MutableTodo::getText, MutableTodo::setText);
249249

250250
assertEquals("Buy milk", textSignal.value());
251251

@@ -259,9 +259,9 @@ void map_multipleFieldMappings_independent() {
259259
MutableTodo todo = new MutableTodo("Task", false);
260260
ValueSignal<MutableTodo> todoSignal = new ValueSignal<>(todo);
261261
WritableSignal<String> textSignal = todoSignal
262-
.map(MutableTodo::getText, MutableTodo::setText);
262+
.mapMutable(MutableTodo::getText, MutableTodo::setText);
263263
WritableSignal<Boolean> doneSignal = todoSignal
264-
.map(MutableTodo::isDone, MutableTodo::setDone);
264+
.mapMutable(MutableTodo::isDone, MutableTodo::setDone);
265265

266266
textSignal.value("Updated task");
267267
assertEquals("Updated task", todo.getText());
@@ -277,7 +277,7 @@ void map_sameInstanceMaintained_afterModification() {
277277
MutableTodo todo = new MutableTodo("Task", false);
278278
ValueSignal<MutableTodo> todoSignal = new ValueSignal<>(todo);
279279
WritableSignal<Boolean> doneSignal = todoSignal
280-
.map(MutableTodo::isDone, MutableTodo::setDone);
280+
.mapMutable(MutableTodo::isDone, MutableTodo::setDone);
281281

282282
doneSignal.value(true);
283283
assertSame(todo, todoSignal.value());

0 commit comments

Comments
 (0)