I've pushed pull request that fixes the issue: https://github.com/groovy/groovy-core/pull/107
The root cause is the existence of getAt(List, Range) and getAt(List, EmptyRange) methods. The second one has been implemented because empty ranges require some special handling. However there is no guarantee that for EmptyRange the getAt(List, EmptyRange) is always called instead of more general getAt(List, Range).
And this is exactly what happens in case of getAt(List, Collection) method.
public static <T> List<T> getAt(List<T> self, Collection indices) {
List<T> answer = new ArrayList<T>(indices.size());
for (Object value : indices) {
if (value instanceof Range) {
answer.addAll(getAt(self, (Range) value));
} else if (value instanceof List) {
answer.addAll(getAt(self, (List) value));
} else {
int idx = DefaultTypeTransformation.intUnbox(value);
answer.add(getAt(self, idx));
}
}
return answer;
}
Each element of collection is tested for being a Range and if it is then the element is explicitly casted to Range and getAt(List, Range) method is called. Because EmptyRange is also a Range more general method is called which causes EmptyRange special handling (provided by getAt(List, EmptyRange)) not being executed.
Explicit casting of EmptyRange to Range is nothing improper what brings us to conclusion that the getAt(List, Range) method shall handle all the ranges - also EmptyRanges since they inherits from Range.
So the fix I pushed adds a check to getAt(List, Range) method if passed range is an instance of EmptyRange. If it is the execution is delegated to specialized method getAt(List, EmptyRange). The test case is also added to ensure proper behavior.
I've pushed pull request that fixes the issue: https://github.com/groovy/groovy-core/pull/107
The root cause is the existence of getAt(List, Range) and getAt(List, EmptyRange) methods. The second one has been implemented because empty ranges require some special handling. However there is no guarantee that for EmptyRange the getAt(List, EmptyRange) is always called instead of more general getAt(List, Range).
And this is exactly what happens in case of getAt(List, Collection) method.
Each element of collection is tested for being a Range and if it is then the element is explicitly casted to Range and getAt(List, Range) method is called. Because EmptyRange is also a Range more general method is called which causes EmptyRange special handling (provided by getAt(List, EmptyRange)) not being executed.
Explicit casting of EmptyRange to Range is nothing improper what brings us to conclusion that the getAt(List, Range) method shall handle all the ranges - also EmptyRanges since they inherits from Range.
So the fix I pushed adds a check to getAt(List, Range) method if passed range is an instance of EmptyRange. If it is the execution is delegated to specialized method getAt(List, EmptyRange). The test case is also added to ensure proper behavior.