eclipse-xtext / eclipse-xtext/xtext
XbaseInterpreter.java:_doEvaluate(XCastedExpression - `throw new EvaluationException(new ClassCastException(typeName))` - not enough information to show to the user what cannot be casted to what
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 831
- Forks
- 330
- Avg merge
- 3d 7h
- Merged PRs (30d)
- 12
Description
class A {
public static void main(String[] arg) {
try {
Object x = Integer.valueOf(0);
System.out.println("A" + (String)x);
} catch (ClassCastException e) {
System.out.println(e.getMessage());
}
}
}
produces with Java 21
$ java A.java
class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of loader 'bootstrap')
That is: ClassCastException.getMessage() is expected to spell both source and target classes of casting.
When XbaseInterpreter.java:protected Object _doEvaluate(XCastedExpression castedExpression, IEvaluationContext, CancelIndicator) creates a ClassCastException, it puts as detailed message the typeName - the target type.
To print a casting error to the user, containing both source and target classes of casting, one has in a derived class to:
override Object _doEvaluate(XCastedExpression castedExpression, IEvaluationContext context, CancelIndicator indicator) {
try {
return super._doEvaluate(castedExpression, context, indicator)
} catch (RuntimeException e) {
if (e.cause instanceof ClassCastException) {
and then constructs a message, containing both source and target types of the casting. Obtaining the target type is easy, it is a matter of calling castedExpression.getType().getType().getQualifiedName(). In fact this is the value of the parameter passed to the constructor of ClassCastException in XbaseInterpreter.java:_doEvaluate(XCastedExpression, IEvaluationContext, CancelIndicator).
However there is no way to know, when the EvaluationException(new ClassCastException()) is catched, what was the source type of the expression: In a as B the class of a.
In openHAB to get the source type is re-executed val Object result = internalEvaluate(castedExpression.getTarget(), context, indicator);. The problem is that calling once val Object result = internalEvaluate(castedExpression.getTarget(), context, indicator); in the super class, and calling again val Object result = internalEvaluate(castedExpression.getTarget(), context, indicator); in the derived class might not necessary have the same result: states might have changed in the meantime, so that re-evaluating the same expression, for the sake of logging an error, might produce no more errors. This in fact does happen, as described at https://github.com/openhab/openhab-core/issues/5323 .
That said in
protected Object _doEvaluate(XCastedExpression castedExpression, IEvaluationContext context, CancelIndic
ator indicator) {
…
try {
expectedType.cast(result);
} catch (ClassCastException e) {
throw new EvaluationException(new ClassCastException(typeName));
}
- spell in the ClassCastException constructor parameter as sentence the target and source types of the casting, as java does in the example of the beginning, or
- instead of passing the target class name (which can be implied when overriding the method by calling
castedExpression.getType().getType().getQualifiedName(), pass the name of the source class.
In both cases the aim is to present to the user a message telling what cannot be casted to what, and currently this is not possible.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with XbaseInterpreter.java at _doEvaluate(XCastedExpression, IEvaluationContext, CancelIndicator) and compare its ClassCastException handling with Java's message. Read openHAB's ScriptInterpreter.xtend usage and openHAB issue 5323 to understand the dangers of re-evaluating the target expression. Done means the resulting evaluation error identifies both source and target types without relying on a second evaluation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100