@@ -140,7 +140,24 @@ private static Object doTransformExpression(Object arg, Function<Expression, ? e
140140 // preserving the type information is hacky and weird (a lot of context needs to be passed around and the lambda itself
141141 // has no type info so it's difficult to have automatic checking without having base classes).
142142
143- if (arg instanceof Collection <?> c ) {
143+ if (arg instanceof List <?> c ) {
144+ List <Object > transformed = null ;
145+ boolean hasChanged = false ;
146+ // please do not refactor it to a for-each loop to avoid
147+ // allocating iterator that performs concurrent modification checks and extra stack frames
148+ for (int i = 0 , size = c .size (); i < size ; i ++) {
149+ var e = c .get (i );
150+ Object next = doTransformExpression (e , traversal );
151+ if (e .equals (next ) == false ) {
152+ if (hasChanged == false ) {
153+ hasChanged = true ;
154+ transformed = new ArrayList <>(c );
155+ }
156+ transformed .set (i , next );
157+ }
158+ }
159+ return hasChanged ? transformed : arg ;
160+ } else if (arg instanceof Collection <?> c ) {
144161 List <Object > transformed = null ;
145162 boolean hasChanged = false ;
146163 int i = 0 ;
@@ -149,13 +166,14 @@ private static Object doTransformExpression(Object arg, Function<Expression, ? e
149166 if (e .equals (next ) == false ) {
150167 if (hasChanged == false ) {
151168 hasChanged = true ;
169+ // TODO if collection is a set then this silently changes its semantics by allowing duplicates
170+ // We should fix it or confirm this branch is never needed
152171 transformed = new ArrayList <>(c );
153172 }
154173 transformed .set (i , next );
155174 }
156175 i ++;
157176 }
158-
159177 return hasChanged ? transformed : arg ;
160178 }
161179
0 commit comments