From 5aeaef82582b6036d0f80eb829bf8fcd1e4c70d2 Mon Sep 17 00:00:00 2001 From: traceyyoshima Date: Mon, 27 Nov 2023 16:04:30 -0700 Subject: [PATCH] Added support for ArrayBindingPattern. --- .../javascript/JavaScriptVisitor.java | 8 ++ .../internal/JavaScriptPrinter.java | 16 +++- .../internal/TypeScriptParserVisitor.java | 28 ++++++- .../org/openrewrite/javascript/tree/JS.java | 73 +++++++++++++++++++ .../javascript/tree/JsContainer.java | 1 + .../javascript/tree/JsRightPadded.java | 1 + .../openrewrite/javascript/tree/JsSpace.java | 3 + .../javascript/tree/DestructureTest.java | 3 - .../javascript/tree/ForLoopTest.java | 14 ++++ .../javascript/tree/TupleTest.java | 3 +- 10 files changed, 142 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/openrewrite/javascript/JavaScriptVisitor.java b/src/main/java/org/openrewrite/javascript/JavaScriptVisitor.java index 3fa40dcc..abe5cea9 100644 --- a/src/main/java/org/openrewrite/javascript/JavaScriptVisitor.java +++ b/src/main/java/org/openrewrite/javascript/JavaScriptVisitor.java @@ -71,6 +71,14 @@ public J visitAlias(JS.Alias alias, P p) { return a; } + public J visitArrayBindingPattern(JS.ArrayBindingPattern arrayBindingPattern, P p) { + JS.ArrayBindingPattern a = arrayBindingPattern; + a = a.withPrefix(visitSpace(a.getPrefix(), JsSpace.Location.ARRAY_BINDING_PATTERN_PREFIX, p)); + a = a.withMarkers(visitMarkers(a.getMarkers(), p)); + a = a.getPadding().withElements(visitContainer(a.getPadding().getElements(), JsContainer.Location.EXPORT_ELEMENT, p)); + return a; + } + public J visitArrowFunction(JS.ArrowFunction arrowFunction, P p) { JS.ArrowFunction a = arrowFunction; a = a.withPrefix(visitSpace(a.getPrefix(), JsSpace.Location.ARROW_FUNCTION_PREFIX, p)); diff --git a/src/main/java/org/openrewrite/javascript/internal/JavaScriptPrinter.java b/src/main/java/org/openrewrite/javascript/internal/JavaScriptPrinter.java index e2fb4515..2c1766e2 100644 --- a/src/main/java/org/openrewrite/javascript/internal/JavaScriptPrinter.java +++ b/src/main/java/org/openrewrite/javascript/internal/JavaScriptPrinter.java @@ -31,6 +31,7 @@ import org.openrewrite.marker.Markers; import java.util.List; +import java.util.Optional; import java.util.function.UnaryOperator; @SuppressWarnings("SameParameterValue") @@ -71,6 +72,14 @@ public J visitAlias(JS.Alias alias, PrintOutputCapture

p) { return alias; } + @Override + public J visitArrayBindingPattern(JS.ArrayBindingPattern arrayBindingPattern, PrintOutputCapture

p) { + beforeSyntax(arrayBindingPattern, JsSpace.Location.ARROW_FUNCTION_PREFIX, p); + visitContainer("[", arrayBindingPattern.getPadding().getElements(), JsContainer.Location.ARRAY_BINDING_ELEMENT, ",", "]", p); + afterSyntax(arrayBindingPattern, p); + return arrayBindingPattern; + } + @Override public J visitArrowFunction(JS.ArrowFunction arrowFunction, PrintOutputCapture

p) { beforeSyntax(arrowFunction, JsSpace.Location.ARROW_FUNCTION_PREFIX, p); @@ -670,8 +679,11 @@ public J visitVariableDeclarations(J.VariableDeclarations multiVariable, PrintOu } if (multiVariable.getTypeExpression() != null) { - multiVariable.getMarkers().findFirst(TypeReferencePrefix.class).ifPresent(typeReferencePrefix -> visitSpace(typeReferencePrefix.getPrefix(), Space.Location.LANGUAGE_EXTENSION, p)); - p.append(":"); + Optional typeReferencePrefix = multiVariable.getMarkers().findFirst(TypeReferencePrefix.class); + if (typeReferencePrefix.isPresent()) { + visitSpace(typeReferencePrefix.get().getPrefix(), Space.Location.LANGUAGE_EXTENSION, p); + p.append(":"); + } visit(multiVariable.getTypeExpression(), p); } diff --git a/src/main/java/org/openrewrite/javascript/internal/TypeScriptParserVisitor.java b/src/main/java/org/openrewrite/javascript/internal/TypeScriptParserVisitor.java index c437102b..18a79b04 100644 --- a/src/main/java/org/openrewrite/javascript/internal/TypeScriptParserVisitor.java +++ b/src/main/java/org/openrewrite/javascript/internal/TypeScriptParserVisitor.java @@ -180,7 +180,20 @@ private J.AssignmentOperation visitAssignmentOperation(TSCNode node) { } private J visitArrayBindingPattern(TSCNode node) { - return unknown(node); + return new JS.ArrayBindingPattern( + randomId(), + whitespace(), + Markers.EMPTY, + mapContainer( + TSCSyntaxKind.OpenBracketToken, + node.getNodeListProperty("elements"), + TSCSyntaxKind.CommaToken, + TSCSyntaxKind.CloseBracketToken, + this::visitNode, + true + ), + typeMapping.type(node) + ); } private J visitArrowFunction(TSCNode node) { @@ -2616,6 +2629,9 @@ private J.VariableDeclarations visitVariableDeclarationList(TSCNode node) { J.Identifier name = null; if (j instanceof J.Identifier) { name = (J.Identifier) j; + } else if (j instanceof TypeTree) { + name = convertToIdentifier(EMPTY, ""); + typeTree = (TypeTree) j; } else { implementMe(declaration); } @@ -2715,6 +2731,9 @@ private J.VariableDeclarations visitVariableStatement(TSCNode node) { J.Identifier name = null; if (j instanceof J.Identifier) { name = (J.Identifier) j; + } else if (j instanceof TypeTree) { + name = convertToIdentifier(EMPTY, ""); + typeTree = (TypeTree) j; } else { implementMe(declaration); } @@ -3250,7 +3269,12 @@ private JContainer mapContainer(TSCSyntaxKind open, List propertyName) { } } + @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) + @EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true) + @RequiredArgsConstructor + @AllArgsConstructor(access = AccessLevel.PRIVATE) + class ArrayBindingPattern implements JS, TypeTree { + + @Nullable + @NonFinal + transient WeakReference padding; + + @Getter + @With + @EqualsAndHashCode.Include + UUID id; + + @Getter + @With + Space prefix; + + @Getter + @With + Markers markers; + + JContainer elements; + + @Getter + @With + @Nullable + JavaType type; + + @Nullable + public List getElements() { + return elements.getElements(); + } + + public ArrayBindingPattern withElements(List elements) { + return getPadding().withElements(JContainer.withElements(this.elements, elements)); + } + + @Override + public

J acceptJavaScript(JavaScriptVisitor

v, P p) { + return v.visitArrayBindingPattern(this, p); + } + + public ArrayBindingPattern.Padding getPadding() { + ArrayBindingPattern.Padding p; + if (this.padding == null) { + p = new ArrayBindingPattern.Padding(this); + this.padding = new WeakReference<>(p); + } else { + p = this.padding.get(); + if (p == null || p.t != this) { + p = new ArrayBindingPattern.Padding(this); + this.padding = new WeakReference<>(p); + } + } + return p; + } + + @RequiredArgsConstructor + public static class Padding { + private final ArrayBindingPattern t; + + public JContainer getElements() { + return t.elements; + } + + public ArrayBindingPattern withElements(JContainer elements) { + return t.elements == elements ? t : new ArrayBindingPattern(t.id, t.prefix, t.markers, elements, t.type); + } + } + } + /** * A JavaScript `=>` is similar to a Java lambda, but additionally contains annotations, modifiers, type arguments. * The ArrowFunction prevents J.Lambda recipes from transforming the LST because an ArrowFunction diff --git a/src/main/java/org/openrewrite/javascript/tree/JsContainer.java b/src/main/java/org/openrewrite/javascript/tree/JsContainer.java index dd9e8166..a92ea869 100644 --- a/src/main/java/org/openrewrite/javascript/tree/JsContainer.java +++ b/src/main/java/org/openrewrite/javascript/tree/JsContainer.java @@ -21,6 +21,7 @@ public class JsContainer { @Getter public enum Location { ARRAY_LITERAL_EXPRESSION(JsSpace.Location.ARRAY_LITERAL_ELEMENTS, JsRightPadded.Location.ARRAY_LITERAL_ELEMENT_SUFFIX), + ARRAY_BINDING_ELEMENT(JsSpace.Location.ARRAY_BINDING_ELEMENTS, JsRightPadded.Location.ARRAY_BINDING_ELEMENT_SUFFIX), BINDING_ELEMENT(JsSpace.Location.BINDING_ELEMENTS, JsRightPadded.Location.BINDING_ELEMENT_SUFFIX), EXPORT_ELEMENT(JsSpace.Location.EXPORT_ELEMENTS, JsRightPadded.Location.EXPORT_ELEMENT_SUFFIX), FUNCTION_TYPE_PARAMETER(JsSpace.Location.FUNCTION_TYPE_PARAMETERS, JsRightPadded.Location.FUNCTION_TYPE_PARAMETER_SUFFIX), diff --git a/src/main/java/org/openrewrite/javascript/tree/JsRightPadded.java b/src/main/java/org/openrewrite/javascript/tree/JsRightPadded.java index a49153e2..76519b64 100644 --- a/src/main/java/org/openrewrite/javascript/tree/JsRightPadded.java +++ b/src/main/java/org/openrewrite/javascript/tree/JsRightPadded.java @@ -22,6 +22,7 @@ public class JsRightPadded { public enum Location { ALIAS_PROPERTY_NAME(JsSpace.Location.ALIAS_PROPERTY_NAME_PREFIX), ARRAY_LITERAL_ELEMENT_SUFFIX(JsSpace.Location.ARRAY_LITERAL_SUFFIX), + ARRAY_BINDING_ELEMENT_SUFFIX(JsSpace.Location.ARRAY_BINDING_ELEMENT_SUFFIX), BINDING_ELEMENT_SUFFIX(JsSpace.Location.BINDING_SUFFIX), BINDING_PROPERTY_NAME_SUFFIX(JsSpace.Location.BINDING_PROPERTY_NAME_SUFFIX), EXPORT_ELEMENT_SUFFIX(JsSpace.Location.EXPORT_ELEMENT_SUFFIX), diff --git a/src/main/java/org/openrewrite/javascript/tree/JsSpace.java b/src/main/java/org/openrewrite/javascript/tree/JsSpace.java index 598c4cbb..a548c02a 100644 --- a/src/main/java/org/openrewrite/javascript/tree/JsSpace.java +++ b/src/main/java/org/openrewrite/javascript/tree/JsSpace.java @@ -22,6 +22,9 @@ public enum Location { ARRAY_LITERAL_PREFIX, ARRAY_LITERAL_ELEMENTS, ARRAY_LITERAL_SUFFIX, + ARRAY_BINDING_PATTERN_PREFIX, + ARRAY_BINDING_ELEMENTS, + ARRAY_BINDING_ELEMENT_SUFFIX, ARROW_FUNCTION_PREFIX, BINARY_PREFIX, BINDING_PREFIX, diff --git a/src/test/java/org/openrewrite/javascript/tree/DestructureTest.java b/src/test/java/org/openrewrite/javascript/tree/DestructureTest.java index 05ce6792..b284057a 100644 --- a/src/test/java/org/openrewrite/javascript/tree/DestructureTest.java +++ b/src/test/java/org/openrewrite/javascript/tree/DestructureTest.java @@ -16,7 +16,6 @@ package org.openrewrite.javascript.tree; import org.junit.jupiter.api.Test; -import org.junitpioneer.jupiter.ExpectedToFail; import org.openrewrite.test.RewriteTest; import static org.openrewrite.javascript.Assertions.javaScript; @@ -24,7 +23,6 @@ @SuppressWarnings("JSUnusedLocalSymbols") class DestructureTest implements RewriteTest { - @ExpectedToFail @Test void destruct() { rewriteRun( @@ -37,7 +35,6 @@ void destruct() { ); } - @ExpectedToFail @Test void varArg() { rewriteRun( diff --git a/src/test/java/org/openrewrite/javascript/tree/ForLoopTest.java b/src/test/java/org/openrewrite/javascript/tree/ForLoopTest.java index b0f7529c..5aa88e8f 100644 --- a/src/test/java/org/openrewrite/javascript/tree/ForLoopTest.java +++ b/src/test/java/org/openrewrite/javascript/tree/ForLoopTest.java @@ -17,6 +17,7 @@ import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.ExpectedToFail; +import org.junitpioneer.jupiter.Issue; import org.openrewrite.test.RewriteTest; import static org.openrewrite.javascript.Assertions.javaScript; @@ -86,4 +87,17 @@ void destruct() { ) ); } + + @Issue("https://github.com/openrewrite/rewrite-javascript/issues/83") + @Test + void arrayBindingPattern() { + rewriteRun( + javaScript( + """ + for (const [ , ] of undefined) { + } + """ + ) + ); + } } diff --git a/src/test/java/org/openrewrite/javascript/tree/TupleTest.java b/src/test/java/org/openrewrite/javascript/tree/TupleTest.java index c466d124..1e7f3b0e 100644 --- a/src/test/java/org/openrewrite/javascript/tree/TupleTest.java +++ b/src/test/java/org/openrewrite/javascript/tree/TupleTest.java @@ -17,6 +17,7 @@ import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.ExpectedToFail; +import org.openrewrite.Issue; import org.openrewrite.test.RewriteTest; import static org.openrewrite.javascript.Assertions.javaScript; @@ -72,7 +73,7 @@ function concat(arr1, arr2) { ); } - @ExpectedToFail("Requires ArrayBindingPattern.") + @Issue("https://github.com/openrewrite/rewrite-javascript/issues/83") @Test void arrayBindingPattern() { rewriteRun(