Skip to content

Commit

Permalink
Normalize spread operator on ArrayLiteral
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 610918324
  • Loading branch information
jDramaix authored and copybara-github committed Feb 28, 2024
1 parent 48d6a8f commit e123dd9
Showing 1 changed file with 72 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,22 @@
import com.google.j2cl.transpiler.ast.AbstractRewriter;
import com.google.j2cl.transpiler.ast.ArrayLiteral;
import com.google.j2cl.transpiler.ast.AstUtils;
import com.google.j2cl.transpiler.ast.Expression;
import com.google.j2cl.transpiler.ast.NewArray;
import com.google.j2cl.transpiler.ast.Node;
import com.google.j2cl.transpiler.ast.NullLiteral;
import com.google.j2cl.transpiler.ast.NumberLiteral;
import com.google.j2cl.transpiler.ast.PrefixExpression;
import com.google.j2cl.transpiler.ast.PrefixOperator;
import com.google.j2cl.transpiler.ast.Type;
import java.util.List;

/**
* Rewrites the rare short form array literal initializers (like "int[] foo = {1, 2, 3};") into the
* more common long form (like "int[] foo = new int[] {1, 2, 3};").
*
* <p>Remove spread operator on an Array present in an array initializer: `new int[] {...new int[]
* {1,2,3}} -> new int[] {1,2,3}
*/
public class NormalizeArrayLiterals extends NormalizationPass {

Expand All @@ -49,5 +58,68 @@ public Node rewriteArrayLiteral(ArrayLiteral arrayLiteral) {
.build();
}
});

// Remove spread operator on an Array inside an ArrayLiteral:
// `new int[] {...new int[] {1,2,3}} -> new int[] {1,2,3}
type.accept(
new AbstractRewriter() {
@Override
public Node rewriteNewArray(NewArray newArray) {
if (!(newArray.getInitializer() instanceof ArrayLiteral)) {
return newArray;
}

ArrayLiteral arrayLiteral = (ArrayLiteral) newArray.getInitializer();
if (arrayLiteral.getValueExpressions().size() != 1) {
// we only support the case where the spread operation is the only element of the
// array initializer.
return newArray;
}

Expression uniqueElement = arrayLiteral.getValueExpressions().get(0);
if (!isRedundantSpreadOperator(uniqueElement)) {
// The element is not on the form `...new int[] {1,2,3}`
return newArray;
}

return ((PrefixExpression) uniqueElement).getOperand();
}
});
}

private static boolean isRedundantSpreadOperator(Expression expression) {
if (!(expression instanceof PrefixExpression)) {
return false;
}

PrefixExpression prefixExpression = (PrefixExpression) expression;

if (prefixExpression.getOperator() != PrefixOperator.SPREAD) {
return false;
}

if (!(prefixExpression.getOperand() instanceof NewArray)) {
return false;
}

NewArray newArrayExpression = (NewArray) prefixExpression.getOperand();

if (newArrayExpression.getInitializer() instanceof ArrayLiteral) {
// Spread operation is redundant on new int[] {1,2,..}
return true;
}

List<Expression> dimensions = newArrayExpression.getDimensionExpressions();

// Spread operation is redundant on new Foo[0] or new Foo[0][][]
return newArrayExpression.getInitializer() == null
&& !dimensions.isEmpty()
&& dimensions.get(0) instanceof NumberLiteral
&& ((NumberLiteral) dimensions.get(0)).getValue().intValue() == 0
&& isAllNullLiterals(dimensions.subList(1, dimensions.size()));
}

private static boolean isAllNullLiterals(List<Expression> expressions) {
return expressions.stream().allMatch(e -> e instanceof NullLiteral);
}
}

0 comments on commit e123dd9

Please sign in to comment.