You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is design problem of already merged CtQueryable#map and CtQuery#list functions. If we solve it correctly, then we can probably use common interface for CtBaseQuery and CtQuery in PR #1076.
Problem: The query uses this API with method list for returning of the query results:
publicinterfaceCtQuery<O> extendsCtQueryable {
/** * actually evaluates the query and returns all the produced elements collected in a List * @return the list of elements collected by the query. */List<O> list();
...
}
The type of items of query result list is generic type O.
Problem 1)
we cannot assure that query will return only objects of type O. So it can happen that we create List<CtClass<?>>, which will contain for example items of type CtElement ... what can then fail with ClassCastException during iteration through such result list.
Solution:
To use these two list methods instead:
/** * actually evaluates the query and returns all the produced elements collected in a List * @return the list of elements collected by the query. */List<Object> list();
/** * actually evaluates the query and returns only the produced elements collected in a List, * which are assignable to `resultType` * @return the filtered list of elements collected by the query. */
<O> List<O> list(Class<O> resultType); //may be we do not need such method at all and the first one is enough.
Please note also where the result list type comes from, because it points to another related change request in the design of the queries:
Note that type R of return value of the map function defines type of returned CtQuery.
So you can write code like this:
List<CtPackage> p = element.map((CtElemente)->e.getParent(CtPackage.class)).list();
but all this causes compile error:
List<Object> p = element.map((CtElemente)->e.getParent(CtPackage.class)).list();
List<CtElement> p = element.map((CtElemente)->e.getParent(CtPackage.class)).list();
... so I have found that it is sometime quite tricky to make it compilable ...
Another real problem is when you start to create variables to store a query.
This works:
CtQuery<CtPackage> aQuery = element.map((CtElemente)->e.getParent(CtPackage.class));
List<CtPackage> p = aQuery.list();
but this is compilable, but will cause class cast exceptions at runtime
CtQuery<CtPackage> aQuery = element.map((CtElemente)->e.getParent(CtPackage.class));
aQuery.filterChildren(newTypeFilter(CtMethod.class));
List<CtPackage> p = aQuery.list();
... because the returned list will contain instances of CtMethod!!!
I am going to make a small PR which solves only this problem, by using List<Object> CtQuery#list() + by removing generic parameter O from the CtQuery interface.
@monperrus, please give me a feedback if such solution is ok for you. Or do you have different idea?
What about <O> List<O> CtQuery#list(Class<O> filter)?
I will then update PR #1076 too.
I will have probably time for both things tomorrow evening.
The text was updated successfully, but these errors were encountered:
I am going to make a small PR which solves only this problem, by using List<Object> CtQuery#list() + by removing generic parameter O from the CtQuery interface. @monperrus, please give me a feedback if such solution is ok for you.
OK for me. We have already too many generics in Spoon that are just painful.
What about <O> List<O> CtQuery#list(Class filter)?
This is design problem of already merged
CtQueryable#map
andCtQuery#list
functions. If we solve it correctly, then we can probably use common interface for CtBaseQuery and CtQuery in PR #1076.Problem: The query uses this API with method
list
for returning of the query results:The type of items of query result list is generic type
O
.Problem 1)
O
. So it can happen that we create List<CtClass<?>>, which will contain for example items of type CtElement ... what can then fail with ClassCastException during iteration through such result list.Solution:
To use these two list methods instead:
Please note also where the result list type comes from, because it points to another related change request in the design of the queries:
Note that type
R
of return value of themap
function defines type of returnedCtQuery
.So you can write code like this:
but all this causes compile error:
... so I have found that it is sometime quite tricky to make it compilable ...
Another real problem is when you start to create variables to store a query.
This works:
but this is compilable, but will cause class cast exceptions at runtime
... because the returned list will contain instances of CtMethod!!!
I am going to make a small PR which solves only this problem, by using
List<Object> CtQuery#list()
+ by removing generic parameterO
from the CtQuery interface.@monperrus, please give me a feedback if such solution is ok for you. Or do you have different idea?
What about
<O> List<O> CtQuery#list(Class<O> filter)
?I will then update PR #1076 too.
I will have probably time for both things tomorrow evening.
The text was updated successfully, but these errors were encountered: