Skip to content

Commit

Permalink
Add JS.Unary to support spread operator (#93)
Browse files Browse the repository at this point in the history
* Add JS.Unary to support spread operator

* Polish.

---------

Co-authored-by: traceyyoshima <[email protected]>
  • Loading branch information
kunli2 and traceyyoshima authored Nov 30, 2023
1 parent d0ffc22 commit b0b6362
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 3 deletions.
22 changes: 22 additions & 0 deletions src/main/java/org/openrewrite/javascript/JavaScriptVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,28 @@ public J visitTypeOperator(JS.TypeOperator typeOperator, P p) {
return t;
}

public J visitUnary(JS.Unary unary, P p) {
JS.Unary u = unary;
u = u.withPrefix(visitSpace(u.getPrefix(), Space.Location.UNARY_PREFIX, p));
u = u.withMarkers(visitMarkers(u.getMarkers(), p));
Statement temp = (Statement) visitStatement(u, p);
if (!(temp instanceof JS.Unary)) {
return temp;
} else {
u = (JS.Unary) temp;
}
Expression temp2 = (Expression) visitExpression(u, p);
if (!(temp2 instanceof JS.Unary)) {
return temp2;
} else {
u = (JS.Unary) temp2;
}
u = u.getPadding().withOperator(visitLeftPadded(u.getPadding().getOperator(), JLeftPadded.Location.UNARY_OPERATOR, p));
u = u.withExpression(visitAndCast(u.getExpression(), p));
u = u.withType(visitType(u.getType(), p));
return u;
}

public J visitUnion(JS.Union union, P p) {
JS.Union u = union;
u = u.withPrefix(visitSpace(u.getPrefix(), JsSpace.Location.UNION_PREFIX, p));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,22 @@ public J visitTypeOperator(JS.TypeOperator typeOperator, PrintOutputCapture<P> p
return typeOperator;
}

@Override
public J visitUnary(JS.Unary unary, PrintOutputCapture<P> p) {
beforeSyntax(unary, Space.Location.UNARY_PREFIX, p);
switch (unary.getOperator()) {
case Spread:
visitSpace(unary.getPadding().getOperator().getBefore(), Space.Location.UNARY_OPERATOR, p);
p.append("...");
visit(unary.getExpression(), p);
break;
default:
break;
}
afterSyntax(unary, p);
return unary;
}

@Override
public J visitUnion(JS.Union union, PrintOutputCapture<P> p) {
beforeSyntax(union, JsSpace.Location.UNION_PREFIX, p);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2067,6 +2067,19 @@ private JRightPadded<Statement> visitStatement(TSCNode node) {
return maybeSemicolon(statement);
}

private J visitSpreadElement(TSCNode node) {
Space prefix = whitespace();
consumeToken(TSCSyntaxKind.DotDotDotToken);
return new JS.Unary(
randomId(),
prefix,
Markers.EMPTY,
padLeft(Space.EMPTY, JS.Unary.Type.Spread),
convertToExpression(visitNode(node.getNodeProperty("expression"))),
null
);
}

private J.Literal visitStringLiteral(TSCNode node) {
implementMe(node, "singleQuote");
if (node.getBooleanProperty("hasExtendedUnicodeEscape")) {
Expand Down Expand Up @@ -3015,6 +3028,9 @@ private J visitNode(@Nullable TSCNode node) {
case ReturnStatement:
j = visitReturnStatement(node);
break;
case SpreadElement:
j = visitSpreadElement(node);
break;
case StringLiteral:
j = visitStringLiteral(node);
break;
Expand Down
112 changes: 112 additions & 0 deletions src/main/java/org/openrewrite/javascript/tree/JS.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import lombok.experimental.NonFinal;
import org.openrewrite.*;
import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.java.JavaPrinter;
import org.openrewrite.java.internal.TypesInUse;
import org.openrewrite.java.service.ImportService;
import org.openrewrite.java.tree.*;
Expand All @@ -39,6 +40,8 @@
import java.util.UUID;
import java.util.stream.Collectors;

import static java.util.Collections.singletonList;

@SuppressWarnings("unused")
public interface JS extends J {

Expand Down Expand Up @@ -1711,6 +1714,115 @@ public JS.TypeOperator withExpression(JLeftPadded<Expression> expression) {
}
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true)
@RequiredArgsConstructor
@AllArgsConstructor(access = AccessLevel.PRIVATE)
final class Unary implements JS, Statement, Expression, TypedTree {
@Nullable
@NonFinal
transient WeakReference<JS.Unary.Padding> padding;

@With
@EqualsAndHashCode.Include
@Getter
UUID id;

@With
@Getter
Space prefix;

@With
@Getter
Markers markers;

JLeftPadded<Type> operator;

public Type getOperator() {
return operator.getElement();
}

public JS.Unary withOperator(Type operator) {
return getPadding().withOperator(this.operator.withElement(operator));
}

@With
@Getter
Expression expression;

@With
@Nullable
@Getter
JavaType type;

@Override
public <R extends Tree, P> R accept(TreeVisitor<R, P> v, P p) {
return JS.super.accept(v, p);
}

@Override
public <P> J acceptJavaScript(JavaScriptVisitor<P> v, P p) {
return v.visitUnary(this, p);
}

@Override
public CoordinateBuilder.Statement getCoordinates() {
return new CoordinateBuilder.Statement(this);
}

@Override
@Transient
public List<J> getSideEffects() {
return getOperator().isModifying() ? singletonList(this) : expression.getSideEffects();
}

@SuppressWarnings("SwitchStatementWithTooFewBranches")
public enum Type {
Spread;

public boolean isModifying() {
switch (this) {
case Spread:
default:
return false;
}
}
}

public JS.Unary.Padding getPadding() {
JS.Unary.Padding p;
if (this.padding == null) {
p = new JS.Unary.Padding(this);
this.padding = new WeakReference<>(p);
} else {
p = this.padding.get();
if (p == null || p.t != this) {
p = new JS.Unary.Padding(this);
this.padding = new WeakReference<>(p);
}
}
return p;
}

@Override
public String toString() {
return withPrefix(Space.EMPTY).printTrimmed(new JavaPrinter<>());
}

@RequiredArgsConstructor
public static class Padding {
private final JS.Unary t;

public JLeftPadded<JS.Unary.Type> getOperator() {
return t.operator;
}

public JS.Unary withOperator(JLeftPadded<JS.Unary.Type> operator) {
return t.operator == operator ? t : new JS.Unary(t.id, t.prefix, t.markers, operator, t.expression, t.type);
}
}
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true)
@RequiredArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ void namedTupleMember() {
);
}

@ExpectedToFail("Requires spread operator")
@Test
void spreadOperators() {
rewriteRun(
Expand Down
17 changes: 15 additions & 2 deletions src/test/java/org/openrewrite/javascript/tree/UnaryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.junitpioneer.jupiter.ExpectedToFail;
import org.junitpioneer.jupiter.Issue;
import org.openrewrite.test.RewriteTest;

import static org.openrewrite.javascript.Assertions.javaScript;

@SuppressWarnings("JSUnusedLocalSymbols")
class UnaryTest implements RewriteTest {

@ParameterizedTest
Expand Down Expand Up @@ -72,5 +73,17 @@ void keyofKeyword() {
);
}


@Issue("https://github.com/openrewrite/rewrite-javascript/issues/82")
@Test
void spreadOperator() {
rewriteRun(
javaScript(
"""
function spread(arr) {
return [...arr]
}
"""
)
);
}
}

0 comments on commit b0b6362

Please sign in to comment.