From 353f9aced868dd397cdc666d948c4ceed715a500 Mon Sep 17 00:00:00 2001 From: Sam Cao Date: Sun, 17 Nov 2024 13:46:09 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20Add=20find()=20to=20ISwc4jA?= =?UTF-8?q?st,=20add=20getMinusCount()=20to=20Swc4jAstNumber?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/release_notes.md | 5 +++ .../swc4j/ast/expr/lit/Swc4jAstNumber.java | 20 +++++++++ .../javet/swc4j/ast/interfaces/ISwc4jAst.java | 38 +++++++++++++++++ .../ast/expr/lit/TestSwc4jAstNumber.java | 26 ++++++++++++ .../swc4j/ast/interfaces/TestISwc4jAst.java | 41 +++++++++++++++++++ 5 files changed, 130 insertions(+) create mode 100644 src/test/java/com/caoccao/javet/swc4j/ast/interfaces/TestISwc4jAst.java diff --git a/docs/release_notes.md b/docs/release_notes.md index 49644d39..0cda5404 100644 --- a/docs/release_notes.md +++ b/docs/release_notes.md @@ -1,5 +1,10 @@ # Release Notes +## 1.3.0 + +* Added `find()` to `ISwc4jAst` +* Added `getMinusCount()` to `Swc4jAstNumber` + ## 1.2.0 * Upgraded deno_ast to v0.43.3 diff --git a/src/main/java/com/caoccao/javet/swc4j/ast/expr/lit/Swc4jAstNumber.java b/src/main/java/com/caoccao/javet/swc4j/ast/expr/lit/Swc4jAstNumber.java index 82154091..2e55901c 100644 --- a/src/main/java/com/caoccao/javet/swc4j/ast/expr/lit/Swc4jAstNumber.java +++ b/src/main/java/com/caoccao/javet/swc4j/ast/expr/lit/Swc4jAstNumber.java @@ -18,6 +18,8 @@ import com.caoccao.javet.swc4j.ast.Swc4jAst; import com.caoccao.javet.swc4j.ast.enums.Swc4jAstType; +import com.caoccao.javet.swc4j.ast.enums.Swc4jAstUnaryOp; +import com.caoccao.javet.swc4j.ast.expr.Swc4jAstUnaryExpr; import com.caoccao.javet.swc4j.ast.interfaces.*; import com.caoccao.javet.swc4j.ast.visitors.ISwc4jAstVisitor; import com.caoccao.javet.swc4j.ast.visitors.Swc4jAstVisitorResponse; @@ -76,6 +78,20 @@ public static Swc4jAstNumber createNaN() { return create(Double.NaN, null); } + protected static int getMinusCount(ISwc4jAst ast) { + switch (ast.getType()) { + case ParenExpr: + return getMinusCount(ast.getParent()); + case UnaryExpr: + if (ast.as(Swc4jAstUnaryExpr.class).getOp() == Swc4jAstUnaryOp.Minus) { + return getMinusCount(ast.getParent()) + 1; + } + return 0; + default: + return 0; + } + } + protected static String normalize(String raw) { Matcher matcher = PATTERN_SCIENTIFIC_NOTATION_WITH_FRACTION.matcher(raw); if (matcher.matches()) { @@ -176,6 +192,10 @@ public List getChildNodes() { return EMPTY_CHILD_NODES; } + public int getMinusCount() { + return getMinusCount(getParent()); + } + @Jni2RustMethod public Optional getRaw() { return raw; diff --git a/src/main/java/com/caoccao/javet/swc4j/ast/interfaces/ISwc4jAst.java b/src/main/java/com/caoccao/javet/swc4j/ast/interfaces/ISwc4jAst.java index 7884af44..1533a951 100644 --- a/src/main/java/com/caoccao/javet/swc4j/ast/interfaces/ISwc4jAst.java +++ b/src/main/java/com/caoccao/javet/swc4j/ast/interfaces/ISwc4jAst.java @@ -22,6 +22,7 @@ import com.caoccao.javet.swc4j.jni2rust.Jni2RustMethod; import com.caoccao.javet.swc4j.span.Swc4jSpan; import com.caoccao.javet.swc4j.utils.AssertionUtils; +import com.caoccao.javet.swc4j.utils.SimpleList; import java.util.List; import java.util.Optional; @@ -55,6 +56,42 @@ default Optional eval() { return Optional.empty(); } + /** + * Find by class without depth limit. + * + * @param the type parameter + * @param clazz the class + * @return the list of AST nodes + * @since 1.3.0 + */ + default List find(Class clazz) { + return find(clazz, -1); + } + + /** + * Find by class with depth limit. + * + * @param the type parameter + * @param clazz the class + * @param depth the depth + * @return the list of AST nodes + * @since 1.3.0 + */ + default List find(Class clazz, int depth) { + AssertionUtils.notNull(clazz, "Class"); + List nodes = SimpleList.of(); + getChildNodes().forEach((childNode) -> { + if (clazz.isAssignableFrom(childNode.getClass())) { + nodes.add(childNode); + } + if (depth != 0) { + final int newDepth = depth > 0 ? depth - 1 : depth; + nodes.addAll(childNode.find(clazz, newDepth)); + } + }); + return nodes; + } + /** * Gets children. * @@ -163,6 +200,7 @@ default boolean isUndefined() { /** * Update parent. + * * @since 0.8.0 */ void updateParent(); diff --git a/src/test/java/com/caoccao/javet/swc4j/ast/expr/lit/TestSwc4jAstNumber.java b/src/test/java/com/caoccao/javet/swc4j/ast/expr/lit/TestSwc4jAstNumber.java index 0ff4ec60..55a18cdf 100644 --- a/src/test/java/com/caoccao/javet/swc4j/ast/expr/lit/TestSwc4jAstNumber.java +++ b/src/test/java/com/caoccao/javet/swc4j/ast/expr/lit/TestSwc4jAstNumber.java @@ -18,12 +18,17 @@ import com.caoccao.javet.swc4j.ast.BaseTestSuiteSwc4jAst; import com.caoccao.javet.swc4j.ast.enums.Swc4jAstType; +import com.caoccao.javet.swc4j.ast.interfaces.ISwc4jAst; import com.caoccao.javet.swc4j.ast.program.Swc4jAstScript; import com.caoccao.javet.swc4j.ast.stmt.Swc4jAstExprStmt; import com.caoccao.javet.swc4j.exceptions.Swc4jCoreException; import com.caoccao.javet.swc4j.outputs.Swc4jParseOutput; +import com.caoccao.javet.swc4j.utils.SimpleMap; import org.junit.jupiter.api.Test; +import java.util.List; +import java.util.Map; + import static org.junit.jupiter.api.Assertions.assertEquals; public class TestSwc4jAstNumber extends BaseTestSuiteSwc4jAst { @@ -71,6 +76,27 @@ public void testDouble() throws Swc4jCoreException { assertSpan(code, script); } + @Test + public void testGetMinusCount() throws Swc4jCoreException { + Map testCaseMap = SimpleMap.of( + "12345", 0, + "-12345", 1, + "(-12345)", 1, + "-(-12345)", 2, + "-(-(-12345))", 3); + for (Map.Entry entry : testCaseMap.entrySet()) { + String code = entry.getKey(); + int minusCount = entry.getValue(); + Swc4jParseOutput output = swc4j.parse(code, tsScriptParseOptions); + List nodes = output.getProgram().find(Swc4jAstNumber.class); + assertEquals(1, nodes.size()); + Swc4jAstNumber number = nodes.get(0).as(Swc4jAstNumber.class); + assertEquals(12345, number.asInt()); + assertEquals("12345", number.getRaw().get()); + assertEquals(minusCount, number.getMinusCount()); + } + } + @Test public void testInt() throws Swc4jCoreException { String code = "12345"; diff --git a/src/test/java/com/caoccao/javet/swc4j/ast/interfaces/TestISwc4jAst.java b/src/test/java/com/caoccao/javet/swc4j/ast/interfaces/TestISwc4jAst.java new file mode 100644 index 00000000..7af09d1d --- /dev/null +++ b/src/test/java/com/caoccao/javet/swc4j/ast/interfaces/TestISwc4jAst.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024. caoccao.com Sam Cao + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.caoccao.javet.swc4j.ast.interfaces; + +import com.caoccao.javet.swc4j.ast.BaseTestSuiteSwc4jAst; +import com.caoccao.javet.swc4j.ast.expr.lit.Swc4jAstNumber; +import com.caoccao.javet.swc4j.exceptions.Swc4jCoreException; +import com.caoccao.javet.swc4j.outputs.Swc4jParseOutput; +import org.junit.jupiter.api.Test; + +import java.util.stream.IntStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class TestISwc4jAst extends BaseTestSuiteSwc4jAst { + @Test + public void testFind() throws Swc4jCoreException { + String code = "+(-(+(-1)))"; + Swc4jParseOutput output = swc4j.parse(code, tsScriptParseOptions); + IntStream.range(0, 7).forEach(i -> + assertTrue(output.getProgram().find(Swc4jAstNumber.class, i).isEmpty())); + assertEquals(1, output.getProgram().find(Swc4jAstNumber.class, 8).size()); + assertEquals(1, output.getProgram().find(Swc4jAstNumber.class, -1).size()); + assertEquals(1, output.getProgram().find(Swc4jAstNumber.class).size()); + } +}