Skip to content

Commit

Permalink
✨ feat: Add join split
Browse files Browse the repository at this point in the history
  • Loading branch information
caoccao committed May 21, 2024
1 parent c63940d commit 91a0ca8
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 79 deletions.
150 changes: 81 additions & 69 deletions src/main/java/com/caoccao/javet/swc4j/ast/expr/Swc4jAstCallExpr.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,14 @@
import com.caoccao.javet.swc4j.span.Swc4jSpan;
import com.caoccao.javet.swc4j.utils.AssertionUtils;
import com.caoccao.javet.swc4j.utils.SimpleList;
import com.caoccao.javet.swc4j.utils.SimpleSet;
import com.caoccao.javet.swc4j.utils.StringUtils;

import java.util.List;
import java.util.Optional;
import java.util.Set;

@Jni2RustClass(filePath = Jni2RustFilePath.AstUtils)
public class Swc4jAstCallExpr
extends Swc4jAst
implements ISwc4jAstExpr {
public static final String FONTCOLOR = "fontcolor";
public static final String ITALICS = "italics";
public static final String TO_STRING = "toString";
public static final Set<String> BUILT_IN_FUNCTION_SET = SimpleSet.immutableOf(FONTCOLOR, ITALICS);
public static final String SLICE = "slice";
public static final String CONCAT = "concat";
protected static final Swc4jParseOptions PARSE_OPTIONS = new Swc4jParseOptions()
.setCaptureAst(true)
.setMediaType(Swc4jMediaType.JavaScript);
Expand Down Expand Up @@ -87,51 +78,99 @@ public Optional<ISwc4jAst> eval() {
Optional<String> call = memberExpr.evalAsCall();
if (call.isPresent()) {
ISwc4jAstExpr obj = memberExpr.getObj().unParenExpr();
if (BUILT_IN_FUNCTION_SET.contains(call.get())) {
if (obj instanceof Swc4jAstStr) {
String objString = obj.as(Swc4jAstStr.class).getValue();
if (FONTCOLOR.equals(call.get())) {
String argString = Swc4jAstIdent.UNDEFINED;
if (!args.isEmpty()) {
Swc4jAstExprOrSpread exprOrSpread = args.get(0);
ISwc4jAstExpr expr = exprOrSpread.getExpr().unParenExpr();
if (expr instanceof Swc4jAstStr || expr instanceof Swc4jAstNumber) {
argString = expr.as(ISwc4jAstCoercionPrimitive.class).asString();
} else if (expr.isNaN()) {
argString = Swc4jAstNumber.NAN;
} else if (expr.isInfinity()) {
argString = Swc4jAstNumber.INFINITY;
} else {
return Optional.empty();
}
}
try {
String escapeArgString = argString.replace("\"", "&quot;");
return Optional.of(Swc4jAstStr.create("<font color=\"" + escapeArgString + "\">" + objString + "</font>"));
} catch (Throwable ignored) {
if (obj instanceof Swc4jAstStr) {
Swc4jAstStr objString = obj.as(Swc4jAstStr.class);
if (Swc4jAstStr.FONTCOLOR.equals(call.get())) {
String argString = Swc4jAstIdent.UNDEFINED;
if (!args.isEmpty()) {
Swc4jAstExprOrSpread exprOrSpread = args.get(0);
ISwc4jAstExpr expr = exprOrSpread.getExpr().unParenExpr();
if (expr instanceof Swc4jAstStr || expr instanceof Swc4jAstNumber) {
argString = expr.as(ISwc4jAstCoercionPrimitive.class).asString();
} else if (expr.isNaN()) {
argString = Swc4jAstNumber.NAN;
} else if (expr.isInfinity()) {
argString = Swc4jAstNumber.INFINITY;
} else {
return Optional.empty();
}
} else if (ITALICS.equals(call.get())) {
return Optional.of(Swc4jAstStr.create("<i>" + objString + "</i>"));
}
return Optional.of(Swc4jAstStr.create(objString.fontcolor(argString)));
} else if (Swc4jAstStr.ITALICS.equals(call.get())) {
return Optional.of(Swc4jAstStr.create(objString.italics()));
} else if (Swc4jAstStr.SPLIT.equals(call.get())) {
switch (args.size()) {
case 0:
return Optional.of(Swc4jAstArrayLit.create(objString.split()));
case 1:
ISwc4jAstExpr arg = args.get(0).getExpr().unParenExpr();
if (arg instanceof ISwc4jAstCoercionPrimitive) {
String separator = arg.as(ISwc4jAstCoercionPrimitive.class).asString();
return Optional.of(Swc4jAstArrayLit.create(objString.split(separator)));
}
break;
default:
ISwc4jAstExpr arg1 = args.get(0).getExpr().unParenExpr();
ISwc4jAstExpr arg2 = args.get(1).getExpr().unParenExpr();
if (arg1 instanceof ISwc4jAstCoercionPrimitive &&
arg2 instanceof ISwc4jAstCoercionPrimitive) {
String separator = arg1.as(ISwc4jAstCoercionPrimitive.class).asString();
int limit = arg2.as(ISwc4jAstCoercionPrimitive.class).asInt();
return Optional.of(Swc4jAstArrayLit.create(objString.split(separator, limit)));
}
break;
}
} else if (Swc4jAstStr.SLICE.equals(call.get())) {
switch (args.size()) {
case 0:
return Optional.of(Swc4jAstStr.create(objString.slice()));
case 1:
ISwc4jAstExpr arg = args.get(0).getExpr().unParenExpr();
if (arg instanceof ISwc4jAstCoercionPrimitive) {
int indexStart = arg.as(ISwc4jAstCoercionPrimitive.class).asInt();
return Optional.of(Swc4jAstStr.create(objString.slice(indexStart)));
}
break;
default:
ISwc4jAstExpr arg1 = args.get(0).getExpr().unParenExpr();
ISwc4jAstExpr arg2 = args.get(1).getExpr().unParenExpr();
if (arg1 instanceof ISwc4jAstCoercionPrimitive &&
arg2 instanceof ISwc4jAstCoercionPrimitive) {
int indexStart = arg1.as(ISwc4jAstCoercionPrimitive.class).asInt();
int indexEnd = arg2.as(ISwc4jAstCoercionPrimitive.class).asInt();
return Optional.of(Swc4jAstStr.create(objString.slice(indexStart, indexEnd)));
}
break;
}
}
} else if (obj instanceof Swc4jAstArrayLit) {
if (CONCAT.equals(call.get())) {
Swc4jAstArrayLit objArrayLit = obj.as(Swc4jAstArrayLit.class);
if (Swc4jAstArrayLit.CONCAT.equals(call.get())) {
if (!args.isEmpty()) {
ISwc4jAstExpr expr = args.get(0).getExpr().unParenExpr();
if (expr instanceof Swc4jAstArrayLit) {
Swc4jAstArrayLit leftArrayLit = obj.as(Swc4jAstArrayLit.class);
Swc4jAstArrayLit rightArrayLit = expr.as(Swc4jAstArrayLit.class);
leftArrayLit.concat(rightArrayLit);
return Optional.of(leftArrayLit);
objArrayLit.concat(rightArrayLit);
return Optional.of(objArrayLit);
}
}
} else if (Swc4jAstArrayLit.JOIN.equals(call.get())) {
if (objArrayLit.isAllPrimitive()) {
String separator = null;
if (!args.isEmpty()) {
ISwc4jAstExpr expr = args.get(0).getExpr().unParenExpr();
if (!expr.isUndefined() && expr instanceof ISwc4jAstCoercionPrimitive) {
separator = expr.as(ISwc4jAstCoercionPrimitive.class).asString();
}
}
return Optional.of(Swc4jAstStr.create(objArrayLit.join(separator)));
}
} else {
return Optional.of(Swc4jAstStr.create(Swc4jAstArrayLit.ARRAY_FUNCTION_STRING_MAP
.getOrDefault(call.get(), Swc4jAstIdent.UNDEFINED)));
}
} else if (Swc4jAstMemberExpr.CONSTRUCTOR.equals(call.get())) {
if (obj instanceof Swc4jAstRegex) {
} else if (obj instanceof Swc4jAstRegex) {
if (Swc4jAstMemberExpr.CONSTRUCTOR.equals(call.get())) {
switch (args.size()) {
case 0:
return Optional.of(Swc4jAstRegex.create());
Expand All @@ -153,43 +192,16 @@ public Optional<ISwc4jAst> eval() {
break;
}
}
} else if (SLICE.equals(call.get())) {
if (obj instanceof Swc4jAstStr) {
String objString = obj.as(Swc4jAstStr.class).getValue();
switch (args.size()) {
case 0:
return Optional.of(Swc4jAstStr.create(objString));
case 1:
ISwc4jAstExpr arg = args.get(0).getExpr().unParenExpr();
if (arg instanceof ISwc4jAstCoercionPrimitive) {
int indexStart = arg.as(ISwc4jAstCoercionPrimitive.class).asInt();
int indexEnd = objString.length();
return Optional.of(Swc4jAstStr.create(StringUtils.slice(objString, indexStart, indexEnd)));
}
break;
default:
ISwc4jAstExpr arg1 = args.get(0).getExpr().unParenExpr();
ISwc4jAstExpr arg2 = args.get(1).getExpr().unParenExpr();
if (arg1 instanceof ISwc4jAstCoercionPrimitive &&
arg2 instanceof ISwc4jAstCoercionPrimitive) {
int indexStart = arg1.as(ISwc4jAstCoercionPrimitive.class).asInt();
int indexEnd = arg2.as(ISwc4jAstCoercionPrimitive.class).asInt();
return Optional.of(Swc4jAstStr.create(StringUtils.slice(objString, indexStart, indexEnd)));
}
break;
}
}
} else if (TO_STRING.equals(call.get())) {
if (obj instanceof Swc4jAstNumber) {
} else if (obj instanceof Swc4jAstNumber) {
if (Swc4jAstNumber.TO_STRING.equals(call.get())) {
int radix = 10;
if (!args.isEmpty()) {
ISwc4jAstExpr arg = args.get(0).getExpr().unParenExpr();
if (arg instanceof Swc4jAstNumber || arg instanceof Swc4jAstStr) {
radix = arg.as(ISwc4jAstCoercionPrimitive.class).asInt();
}
}
String value = Integer.toString(obj.as(Swc4jAstNumber.class).asInt(), radix);
return Optional.of(Swc4jAstStr.create(value));
return Optional.of(Swc4jAstStr.create(obj.as(Swc4jAstNumber.class).toString(radix)));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ public Swc4jAstExprOrSpread(
setSpread(spread);
}

public static Swc4jAstExprOrSpread create(ISwc4jAstExpr expr) {
return new Swc4jAstExprOrSpread(null, expr, Swc4jSpan.DUMMY);
}

@Override
public List<ISwc4jAst> getChildNodes() {
return SimpleList.of(expr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@
import com.caoccao.javet.swc4j.utils.SimpleMap;
import com.caoccao.javet.swc4j.utils.SimpleSet;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;

@Jni2RustClass(filePath = Jni2RustFilePath.AstUtils)
Expand Down Expand Up @@ -104,7 +101,9 @@ public class Swc4jAstArrayLit
"toString", "",
"unshift", "0",
"values", "[object Array Iterator]");
public static final String CONCAT = "concat";
public static final String CONSTRUCTOR = "Array";
public static final String JOIN = "join";
protected final List<Optional<Swc4jAstExprOrSpread>> elems;

@Jni2RustMethod
Expand All @@ -118,6 +117,14 @@ public Swc4jAstArrayLit(
this.elems.stream().filter(Optional::isPresent).map(Optional::get).forEach(node -> node.setParent(this));
}

public static Swc4jAstArrayLit create(List<String> list) {
List<Swc4jAstExprOrSpread> elems = new ArrayList<>();
if (list != null && !list.isEmpty()) {
list.forEach(str -> elems.add(str == null ? null : Swc4jAstExprOrSpread.create(Swc4jAstStr.create(str))));
}
return new Swc4jAstArrayLit(elems, Swc4jSpan.DUMMY);
}

@Override
public boolean asBoolean() {
return true;
Expand Down Expand Up @@ -216,6 +223,19 @@ public boolean isAllPrimitive() {
});
}

public String join(String separator) {
if (separator == null) {
separator = ",";
}
return elems.stream()
.map(elem -> elem
.map(e -> e.getExpr().unParenExpr())
.map(e -> e.as(ISwc4jAstCoercionPrimitive.class))
.map(ISwc4jAstCoercionPrimitive::toString)
.orElse(""))
.collect(Collectors.joining(separator));
}

@Override
public boolean replaceNode(ISwc4jAst oldNode, ISwc4jAst newNode) {
if (!elems.isEmpty() && (newNode == null || newNode instanceof Swc4jAstExprOrSpread)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class Swc4jAstNumber
public static final String CONSTRUCTOR = "Number";
public static final String INFINITY = "Infinity";
public static final String NAN = "NaN";
public static final String TO_STRING = "toString";
protected static final int MAX_EXPONENT = 308;
protected static final Pattern PATTERN_DECIMAL_ZEROS =
Pattern.compile("^([\\+\\-]?)(\\d+)\\.0*$", Pattern.CASE_INSENSITIVE);
Expand All @@ -47,6 +48,7 @@ public class Swc4jAstNumber
@Jni2RustField(componentAtom = true)
protected Optional<String> raw;
protected double value;

@Jni2RustMethod
public Swc4jAstNumber(
double value,
Expand Down Expand Up @@ -222,6 +224,10 @@ public String toString() {
return normalize(raw.orElse(Double.toString(value)));
}

public String toString(int radix) {
return Integer.toString(asInt(), radix);
}

@Override
public Swc4jAstVisitorResponse visit(ISwc4jAstVisitor visitor) {
switch (visitor.visitNumber(this)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public class Swc4jAstStr
implements ISwc4jAstLit, ISwc4jAstModuleExportName, ISwc4jAstPropName, ISwc4jAstTsModuleName, ISwc4jAstTsLit,
ISwc4jAstTsEnumMemberId, ISwc4jAstCoercionPrimitive {
public static final String CONSTRUCTOR = "String";
public static final String FONTCOLOR = "fontcolor";
public static final String ITALICS = "italics";
public static final String SLICE = "slice";
public static final String SPLIT = "split";
@Jni2RustField(componentAtom = true)
protected Optional<String> raw;
@Jni2RustField(atom = true)
Expand Down Expand Up @@ -98,6 +102,11 @@ public String asString() {
return toString();
}

public String fontcolor(String arg) {
String escapeArg = arg.replace("\"", "&quot;");
return "<font color=\"" + escapeArg + "\">" + value + "</font>";
}

@Override
public List<ISwc4jAst> getChildNodes() {
return EMPTY_CHILD_NODES;
Expand All @@ -118,6 +127,10 @@ public String getValue() {
return value;
}

public String italics() {
return "<i>" + value + "</i>";
}

@Override
public boolean replaceNode(ISwc4jAst oldNode, ISwc4jAst newNode) {
return false;
Expand All @@ -133,6 +146,30 @@ public Swc4jAstStr setValue(String value) {
return this;
}

public String slice() {
return slice(0);
}

public String slice(int indexStart) {
return slice(indexStart, value.length());
}

public String slice(int indexStart, int indexEnd) {
return StringUtils.slice(value, indexStart, indexEnd);
}

public List<String> split() {
return split(null, 0);
}

public List<String> split(String separator) {
return split(separator, 0);
}

public List<String> split(String separator, int limit) {
return StringUtils.split(value, separator, limit);
}

@Override
public String toString() {
return value;
Expand Down
Loading

0 comments on commit 91a0ca8

Please sign in to comment.