Skip to content

Commit 7ce7c98

Browse files
committed
Add explicit type check to UpdateStrategy.convert()
When using the DefaultConverter, type erasure may occur, where the "convert" method returns an object of type S, but treats it as type D. The conversion must fail early in such a case, in order to prevent obscure error messages when passing the value to successive methods. Closes #3008
1 parent b141132 commit 7ce7c98

File tree

4 files changed

+35
-4
lines changed

4 files changed

+35
-4
lines changed

bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/UpdateStrategy.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,10 @@ public D convert(S value) {
653653
if (converter != null) {
654654
try {
655655
return converter.convert(value);
656+
} catch (ClassCastException ex) {
657+
String msg = BindingMessages.getString(BindingMessages.TYPE_ERASURE);
658+
Policy.getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, msg, ex));
659+
throw ex;
656660
} catch (Exception ex) {
657661
Policy.getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, ex.getMessage(), ex));
658662
throw ex;
@@ -677,6 +681,10 @@ static final class DefaultConverter implements IConverter<Object, Object> {
677681

678682
@Override
679683
public Object convert(Object fromObject) {
684+
// Explicit cast necessary due to potential type erasure
685+
if (toType instanceof Class<?> clazz) {
686+
return clazz.cast(fromObject);
687+
}
680688
return fromObject;
681689
}
682690

bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/BindingMessages.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2005, 2008 IBM Corporation and others.
2+
* Copyright (c) 2005, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -110,6 +110,11 @@ public class BindingMessages {
110110
*/
111111
public static final String VALIDATE_NUMBER_PARSE_ERROR_NO_CHARACTER = "Validate_NumberParseErrorNoCharacter"; //$NON-NLS-1$
112112

113+
/**
114+
* Key to be used for a "TYPE_ERASURE" message
115+
*/
116+
public static final String TYPE_ERASURE = "Type_Erasure"; //$NON-NLS-1$
117+
113118
/**
114119
* Returns the resource object with the given key in the resource bundle for
115120
* JFace Data Binding. If there isn't any value under the given key, the key

bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/messages.properties

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
###############################################################################
2-
# Copyright (c) 2000, 2008 IBM Corporation and others.
2+
# Copyright (c) 2000, 2025 IBM Corporation and others.
33
#
44
# This program and the accompanying materials
55
# are made available under the terms of the Eclipse Public License 2.0
@@ -56,4 +56,6 @@ Validate_ConversionFromClassToPrimitive="Wrong object type to convert to primiti
5656
Validate_NoChangeAllowedHelp=Changes are not allowed in this field
5757
Validate_CharacterHelp=Please type a character
5858

59-
Examples=Examples
59+
Examples=Examples
60+
61+
Type_Erasure=Value was not converted and type erasure occurred.

tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/databinding/UpdateStrategyTest.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2007 IBM Corporation and others.
2+
* Copyright (c) 2007, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -16,11 +16,15 @@
1616

1717
import static org.junit.Assert.assertEquals;
1818
import static org.junit.Assert.assertNotNull;
19+
import static org.junit.Assert.assertThrows;
1920
import static org.junit.Assert.assertTrue;
2021

2122
import java.math.BigDecimal;
2223
import java.math.BigInteger;
2324
import java.util.Date;
25+
import java.util.HashSet;
26+
import java.util.List;
27+
import java.util.Set;
2428

2529
import org.eclipse.core.databinding.UpdateValueStrategy;
2630
import org.eclipse.core.databinding.conversion.IConverter;
@@ -354,4 +358,16 @@ public UpdateValueStrategy<S, D> setConverter(IConverter<? super S, ? extends D>
354358
return super.setConverter(converter);
355359
}
356360
}
361+
362+
@Test
363+
public void testDefaultConverterWithTypeErasure() {
364+
WritableValue<Set<?>> source = WritableValue.withValueType(Set.class);
365+
WritableValue<List<?>> destination = WritableValue.withValueType(List.class);
366+
367+
UpdateStrategyStub<Set<?>, List<?>> strategy = new UpdateStrategyStub<>();
368+
strategy.fillDefaults(source, destination);
369+
370+
RuntimeException ex = assertThrows(RuntimeException.class, () -> strategy.convert(new HashSet<>()));
371+
assertTrue("Type erasure was missed", ex.getCause() instanceof ClassCastException);
372+
}
357373
}

0 commit comments

Comments
 (0)