diff --git a/docs/release_notes.md b/docs/release_notes.md index 00f9b14..0935d14 100644 --- a/docs/release_notes.md +++ b/docs/release_notes.md @@ -4,7 +4,7 @@ * Added `find()` to `ISwc4jAst` * Added `getMinusCount()` to `Swc4jAstNumber` -* Added `getBangCount()` to `Swc4jAstBinExpr` +* Added `getBangCount()`, `getLogicalOperatorCount()` to `Swc4jAstBinExpr` * Added `getOppositeOperator()`, `isLogicalOperator()`, `isLogicalCompareOperator()`, `isLogicalConditionOperator()` to `Swc4jAstBinaryOp` ## 1.2.0 diff --git a/src/main/java/com/caoccao/javet/swc4j/ast/expr/Swc4jAstBinExpr.java b/src/main/java/com/caoccao/javet/swc4j/ast/expr/Swc4jAstBinExpr.java index 081c354..2d37204 100644 --- a/src/main/java/com/caoccao/javet/swc4j/ast/expr/Swc4jAstBinExpr.java +++ b/src/main/java/com/caoccao/javet/swc4j/ast/expr/Swc4jAstBinExpr.java @@ -53,6 +53,13 @@ public class Swc4jAstBinExpr protected Optional bangCount; @Jni2RustField(box = true) protected ISwc4jAstExpr left; + /** + * The Logical operator count is a local cache of the logical operator count through the AST. + * + * @since 1.3.0 + */ + @Jni2RustField(ignore = true) + protected Optional logicalOperatorCount; protected Swc4jAstBinaryOp op; @Jni2RustField(box = true) protected ISwc4jAstExpr right; @@ -65,6 +72,7 @@ public Swc4jAstBinExpr( Swc4jSpan span) { super(span); resetBangCount(); + resetLogicalOperatorCount(); setLeft(left); setOp(op); setRight(right); @@ -256,6 +264,28 @@ public ISwc4jAstExpr getLeft() { return left; } + public int getLogicalOperatorCount() { + if (!logicalOperatorCount.isPresent()) { + logicalOperatorCount = Optional.of(getLogicalOperatorCount(getParent())); + } + return logicalOperatorCount.get(); + } + + protected int getLogicalOperatorCount(ISwc4jAst ast) { + switch (ast.getType()) { + case BinExpr: + Swc4jAstBinExpr binExpr = ast.as(Swc4jAstBinExpr.class); + if (binExpr.getOp().isLogicalOperator()) { + return binExpr.getLogicalOperatorCount() + 1; + } + return 0; + case ParenExpr: + return getLogicalOperatorCount(ast.getParent()); + default: + return 0; + } + } + @Jni2RustMethod public Swc4jAstBinaryOp getOp() { return op; @@ -289,6 +319,11 @@ public Swc4jAstBinExpr resetBangCount() { return this; } + public Swc4jAstBinExpr resetLogicalOperatorCount() { + logicalOperatorCount = Optional.empty(); + return this; + } + public Swc4jAstBinExpr setLeft(ISwc4jAstExpr left) { this.left = AssertionUtils.notNull(left, "Left"); this.left.setParent(this); diff --git a/src/test/java/com/caoccao/javet/swc4j/ast/expr/TestSwc4jAstBinExpr.java b/src/test/java/com/caoccao/javet/swc4j/ast/expr/TestSwc4jAstBinExpr.java index c08bd73..1cf13b9 100644 --- a/src/test/java/com/caoccao/javet/swc4j/ast/expr/TestSwc4jAstBinExpr.java +++ b/src/test/java/com/caoccao/javet/swc4j/ast/expr/TestSwc4jAstBinExpr.java @@ -26,6 +26,7 @@ import com.caoccao.javet.swc4j.exceptions.Swc4jCoreException; import com.caoccao.javet.swc4j.outputs.Swc4jParseOutput; import com.caoccao.javet.swc4j.plugins.ISwc4jPluginHost; +import com.caoccao.javet.swc4j.utils.SimpleList; import com.caoccao.javet.swc4j.utils.SimpleMap; import org.junit.jupiter.api.Test; @@ -99,6 +100,41 @@ public void testGetBangCount() throws Swc4jCoreException { } } + @Test + public void testGetLogicalOperatorCount() throws Swc4jCoreException { + Map> testCaseMap = SimpleMap.of( + "a==b", SimpleList.of( + 0, Swc4jAstBinaryOp.EqEq), + "a>b||cb||(c==d&&(e+f)<=g)", SimpleList.of( + 0, Swc4jAstBinaryOp.LogicalOr, + 1, Swc4jAstBinaryOp.Gt, + 1, Swc4jAstBinaryOp.LogicalAnd, + 2, Swc4jAstBinaryOp.EqEq, + 2, Swc4jAstBinaryOp.LtEq, + 3, Swc4jAstBinaryOp.Add), + "a>b||((c+d)?e:f)", SimpleList.of( + 0, Swc4jAstBinaryOp.LogicalOr, + 1, Swc4jAstBinaryOp.Gt, + 0, Swc4jAstBinaryOp.Add)); + for (Map.Entry> entry : testCaseMap.entrySet()) { + String code = entry.getKey(); + int size = entry.getValue().size() >> 1; + Swc4jParseOutput output = swc4j.parse(code, tsScriptParseOptions); + List nodes = output.getProgram().find(Swc4jAstBinExpr.class); + assertEquals(size, nodes.size()); + for (int i = 0; i < size; i++) { + Swc4jAstBinExpr binExpr = nodes.get(i); + int index = i << 1; + assertEquals(entry.getValue().get(index + 1), binExpr.getOp()); + assertEquals(entry.getValue().get(index), binExpr.getLogicalOperatorCount()); + } + } + } + @Test public void testOpWithSpace() { Stream.of(Swc4jAstBinaryOp.values())