else if (methodName.equals("set") && numArgs == 2 && isInt(expr.getArg(0).getType()) && isString(expr.getArg(1).getType())) {
// note: List.set returns the element previously at the position
// get the old element
Variable old = factory.createVariable(VariableType.STRING);
factory.addStatement(new StringFromArray(old, callee));
// insert the new element
factory.addStatement(new ArrayWriteElement(callee, arguments.get(1)));
return old;
}
// get(int)
else if (methodName.equals("get") && numArgs == 1 && isInt(expr.getArg(0).getType())) {
Variable result = factory.createVariable(VariableType.STRING);
factory.addStatement(new StringFromArray(result, callee));
return result;
}
// iterator()
else if (methodName.equals("iterator") && numArgs == 0) {
// changes to the collection might reflect on the iterator
// and vice versa (eg using ListIterator.add)
return callee;
}
// listIterator()
else if (methodName.equals("listIterator") && numArgs == 0) {
// changes to the collection might reflect on the iterator
// and vice versa (eg using ListIterator.add)
return callee;
}
// methods without side-effects returning booleans
else if (methodName.equals("contains")
|| methodName.equals("containsAll")
|| methodName.equals("isEmpty")) {
return anybool(factory);
}
// remove() and removeAll() are just identity operations for now
else if (methodName.equals("remove")
|| methodName.equals("removeAll")) {
return anybool(factory);
}
// size()
else if (methodName.equals("size")) {
return factory.getNothing();
}
else if (methodName.equals("toArray") && numArgs == 0) {
Variable result = factory.createVariable(VariableType.ARRAY);
factory.addStatement(new ArrayNew(result));
factory.addStatement(new ArrayAddAll(result, callee));
return result;
}
else if (methodName.equals("toArray") && numArgs == 1) {
Variable result = factory.createVariable(VariableType.ARRAY);
// the elements MIGHT be stored into the argument
factory.startBranch();
// 1) not stored in argument
{
factory.addStatement(new ArrayNew(result));
factory.useBranch();
}
// 2) stored in argument
{
// note: existing elements in the array may remain
// in particular if the array is larger than the collection,
// the exceeding elements are unchanged, so do not clear the array here
factory.addStatement(new ArrayAssignment(result, arguments.get(0)));
factory.useBranch();
}
factory.endBranch();
factory.addStatement(new ArrayAddAll(result, callee));
return result;
}
}
//
// ITERATORS
//
else if (factory.isSubtypeOf(declaringClass, Scene.v().getSootClass("java.util.Iterator"))) {
if (methodName.equals("hasNext") && numArgs == 0) {
return anybool(factory); // no side-effects
}
else if (methodName.equals("hasPrevious") && numArgs == 0) {
return anybool(factory); // no side-effects
}
else if ((methodName.equals("next") || methodName.equals("previous")) && numArgs == 0) {
Variable result = factory.createVariable(VariableType.STRING);
factory.addStatement(new StringFromArray(result, callee));
return result;
}
else if (methodName.equals("remove") && numArgs == 1) {
return anybool(factory); // just prevent corruption
}