/** * @name Inefficient toArray on zero-length argument * @description Calling 'Collection.toArray' with a zero-length array argument is inefficient. * @kind problem * @problem.severity recommendation * @precision low * @id java/inefficient-to-array * @deprecated */ import java /* * This method uses the toArray() method of a collection derived class, and passes in a * zero-length prototype array argument. * * It is more efficient to use myCollection.toArray(new Foo[myCollection.size()]). * If the array passed in is big enough to store all of the elements of the collection, * then it is populated and returned directly. This avoids the need to create a * second array (by reflection) to return as the result. * * The new array has to be created as the argument value. Values in both branches of * a conditional has to be an empty array. */ predicate emptyArrayLiteral(Expr e) { // ArrayCreationExpr with zero-length init expr exists(ArrayCreationExpr arr | arr = e | exists(arr.getInit()) and not exists(arr.getInit().getAnInit()) ) or // ArrayCreationExpr where 0th dimension is zero literal e.(ArrayCreationExpr).getDimension(0).(IntegerLiteral).getIntValue() = 0 or exists(ConditionalExpr cond | cond = e | emptyArrayLiteral(cond.getTrueExpr()) and emptyArrayLiteral(cond.getFalseExpr()) ) } class EmptyArrayLiteral extends Expr { EmptyArrayLiteral() { emptyArrayLiteral(this) } } from EmptyArrayLiteral l, MethodAccess ma, Method m, GenericInterface coll where coll.hasQualifiedName("java.util", "Collection") and ma.getMethod() = m and m.hasName("toArray") and m.getDeclaringType().getASupertype*().getSourceDeclaration() = coll and ma.getArgument(0) = l select ma, "Collection.toArray(...) called with zero-length array argument."