Skip to content

Commit f92dbb2

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 f92dbb2

File tree

4 files changed

+37
-5
lines changed

4 files changed

+37
-5
lines changed

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,16 @@ protected IStatus logErrorWhileSettingValue(Exception ex) {
652652
public D convert(S value) {
653653
if (converter != null) {
654654
try {
655-
return converter.convert(value);
655+
// Explicit cast necessary due to potential type erasure
656+
D result = converter.convert(value);
657+
if (converter.getToType() instanceof Class<?> clazz) {
658+
return (D) clazz.cast(result);
659+
}
660+
return result;
661+
} catch (ClassCastException ex) {
662+
String msg = BindingMessages.getString(BindingMessages.TYPE_ERASURE);
663+
Policy.getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, msg, ex));
664+
throw ex;
656665
} catch (Exception ex) {
657666
Policy.getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, ex.getMessage(), ex));
658667
throw ex;

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 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)