From 3113e63f7db44cd0ebcaa7c4e99e68a58e3e4278 Mon Sep 17 00:00:00 2001 From: Louis Grignon Date: Thu, 16 Jul 2020 01:33:15 +0200 Subject: [PATCH] fix iteration over Set + support Map.entrySet + enable Set methods fallback --- .../extension/Java2TypeScriptAdapter.java | 2 +- .../RemoveJavaDependenciesES6Adapter.java | 23 +- .../java/source/nativestructures/ES6Maps.java | 118 ++++---- .../java/source/nativestructures/ES6Sets.java | 257 +++++++++--------- 4 files changed, 222 insertions(+), 178 deletions(-) diff --git a/transpiler/src/main/java/org/jsweet/transpiler/extension/Java2TypeScriptAdapter.java b/transpiler/src/main/java/org/jsweet/transpiler/extension/Java2TypeScriptAdapter.java index 80b25ab4..4faffc21 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/extension/Java2TypeScriptAdapter.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/extension/Java2TypeScriptAdapter.java @@ -127,7 +127,7 @@ import com.sun.tools.javac.tree.JCTree.Tag; */ public class Java2TypeScriptAdapter extends PrinterAdapter { - private final static String VAR_DECL_KEYWORD = Java2TypeScriptTranslator.VAR_DECL_KEYWORD; + protected final static String VAR_DECL_KEYWORD = Java2TypeScriptTranslator.VAR_DECL_KEYWORD; public Java2TypeScriptTranslator getPrinter() { return (Java2TypeScriptTranslator) super.getPrinter(); diff --git a/transpiler/src/main/java/org/jsweet/transpiler/extension/RemoveJavaDependenciesES6Adapter.java b/transpiler/src/main/java/org/jsweet/transpiler/extension/RemoveJavaDependenciesES6Adapter.java index e8b9edff..91bd04e5 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/extension/RemoveJavaDependenciesES6Adapter.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/extension/RemoveJavaDependenciesES6Adapter.java @@ -36,8 +36,12 @@ import javax.lang.model.type.TypeMirror; import org.jsweet.transpiler.JSweetProblem; import org.jsweet.transpiler.model.ExtendedElement; +import org.jsweet.transpiler.model.ForeachLoopElement; import org.jsweet.transpiler.model.MethodInvocationElement; import org.jsweet.transpiler.model.NewClassElement; +import org.jsweet.transpiler.model.support.ForeachLoopElementSupport; + +import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop; /** * An adapter that removes many uses of Java APIs and replace them with @@ -62,6 +66,19 @@ public class RemoveJavaDependenciesES6Adapter extends RemoveJavaDependenciesAdap super.initTypesMapping(); SET_CLASS_NAMES.forEach(name -> extTypesMapping.put(name, "Set")); MAP_CLASS_NAMES.forEach(name -> extTypesMapping.put(name, "Map")); + extTypesMapping.put(Map.class.getName() + ".Entry", "any"); + } + + @Override + public boolean substituteForEachLoop(ForeachLoopElement foreachLoop, boolean targetHasLength, String indexVarName) { + JCEnhancedForLoop loop = ((ForeachLoopElementSupport) foreachLoop).getTree(); + if (!targetHasLength && SET_CLASS_NAMES.contains(context.types.erasure(loop.expr.type).toString())) { + getPrinter().print(loop.expr).print(".forEach((" + loop.var.name.toString() + ")=>"); + getPrinter().printIndent().print(loop.body); + endIndent().println().printIndent().print(")"); + return true; + } + return super.substituteForEachLoop(foreachLoop, targetHasLength, indexVarName); } @Override @@ -196,7 +213,7 @@ public class RemoveJavaDependenciesES6Adapter extends RemoveJavaDependenciesAdap print("(").print("Array.from(").print(targetExpression).print(")").print(")"); break; default: - report(invocation, JSweetProblem.USER_ERROR, targetMethodName + " is not supported."); + printCallToEponymMethod(invocation); } } @@ -229,9 +246,9 @@ public class RemoveJavaDependenciesES6Adapter extends RemoveJavaDependenciesAdap print(")"); break; - case "entries": + case "entrySet": printMacroName(targetMethodName); - print("((m) => new Set(m.entries()))("); + print("((m) => new Set(Array.from(m.entries()).map(entry => ({ getKey: () => entry[0], getValue: () => entry[1] }) ) ))("); print(targetExpression); print(")"); break; diff --git a/transpiler/src/test/java/source/nativestructures/ES6Maps.java b/transpiler/src/test/java/source/nativestructures/ES6Maps.java index baddd3a6..726f9c3a 100644 --- a/transpiler/src/test/java/source/nativestructures/ES6Maps.java +++ b/transpiler/src/test/java/source/nativestructures/ES6Maps.java @@ -2,62 +2,80 @@ package source.nativestructures; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; public class ES6Maps { - public static void main(String[] args) { - // put / clear - Map m1 = new HashMap<>(); - assert m1.size() == 0; - Integer prev = m1.put("1", 1); - assert prev == null; - assert !m1.isEmpty(); - - Integer prev2 = m1.put("1", 2); - assert prev2 == 1; - assert m1.size() == 1; - - // clear - m1.clear(); - assert m1.size() == 0; - assert m1.isEmpty(); + public static void main(String[] args) { + // put / clear + Map m1 = new HashMap<>(); + assert m1.size() == 0; + Integer prev = m1.put("1", 1); + assert prev == null; + assert !m1.isEmpty(); - // containsKey / containsValue / remove - m1.put("1", 2); - boolean containsKey1 = m1.containsKey("1"); - assert containsKey1; - boolean containsValue1 = m1.containsValue(2); - assert containsValue1; - Integer removed = m1.remove("1"); - assert removed == 2; + Integer prev2 = m1.put("1", 2); + assert prev2 == 1; + assert m1.size() == 1; - boolean containsKey2 = m1.containsKey("1"); - assert !containsKey2; - boolean containsValue2 = m1.containsValue(2); - assert !containsValue2; + // clear + m1.clear(); + assert m1.size() == 0; + assert m1.isEmpty(); - // putAll - Map m2 = new HashMap<>(); - m2.put("1", 2); - m2.put("2", 4); - m1.putAll(m2); - assert m1.size() == 2; - assert m1.get("1") == 2; - assert m1.get("2") == 4; + // containsKey / containsValue / remove + m1.put("1", 2); + boolean containsKey1 = m1.containsKey("1"); + assert containsKey1; + boolean containsValue1 = m1.containsValue(2); + assert containsValue1; + Integer removed = m1.remove("1"); + assert removed == 2; - // new HashMap(Collection<>); - Map m3 = new HashMap<>(m2); - assert m3.size() == 2; - assert m3.get("1") == 2; - assert m3.get("2") == 4; + boolean containsKey2 = m1.containsKey("1"); + assert !containsKey2; + boolean containsValue2 = m1.containsValue(2); + assert !containsValue2; - // new HashMap(int initialCapacity); - Map m4 = new HashMap<>(15); - assert m4.size() == 0; - assert m4.isEmpty(); + // putAll + Map m2 = new HashMap<>(); + m2.put("1", 2); + m2.put("2", 4); + m1.putAll(m2); + assert m1.size() == 2; + assert m1.get("1") == 2; + assert m1.get("2") == 4; - // new HashMap(int initialCapacity, float loadFactor); - m4 = new HashMap<>(15, 89); - assert m4.size() == 0; - assert m4.isEmpty(); - } + // entrySet + Set> entrySet = m2.entrySet(); + assert entrySet.size() == 2; + boolean firstFound = false; + boolean secondFound = false; + for (Entry e : entrySet) { + if (e.getKey() == "1" && e.getValue() == 2) { + firstFound = true; + } else if (e.getKey() == "2" && e.getValue() == 4) { + secondFound = true; + } + } + + assert firstFound; + assert secondFound; + + // new HashMap(Collection<>); + Map m3 = new HashMap<>(m2); + assert m3.size() == 2; + assert m3.get("1") == 2; + assert m3.get("2") == 4; + + // new HashMap(int initialCapacity); + Map m4 = new HashMap<>(15); + assert m4.size() == 0; + assert m4.isEmpty(); + + // new HashMap(int initialCapacity, float loadFactor); + m4 = new HashMap<>(15, 89); + assert m4.size() == 0; + assert m4.isEmpty(); + } } diff --git a/transpiler/src/test/java/source/nativestructures/ES6Sets.java b/transpiler/src/test/java/source/nativestructures/ES6Sets.java index 393b5b09..450aad8d 100644 --- a/transpiler/src/test/java/source/nativestructures/ES6Sets.java +++ b/transpiler/src/test/java/source/nativestructures/ES6Sets.java @@ -1,141 +1,150 @@ package source.nativestructures; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; public class ES6Sets { - public static void main(String[] args) { - // add - Set s1 = new HashSet(); - assert s1.size() == 0; - boolean added = s1.add("1"); - assert added; - s1.add("2"); - boolean added2 = s1.add("2"); - assert !added2; - assert s1.size() == 2; - s1.clear(); - assert s1.size() == 0; + public static void main(String[] args) { + // add + Set s1 = new HashSet(); + assert s1.size() == 0; + boolean added = s1.add("1"); + assert added; + s1.add("2"); + boolean added2 = s1.add("2"); + assert !added2; + assert s1.size() == 2; + s1.clear(); + assert s1.size() == 0; - // remove - Set s2 = new HashSet<>(); - s2.add("1"); - assert s2.size() == 1; - assert s2.remove("1"); - assert s2.size() == 0; - s2.add("2"); - assert !s2.remove("1"); - assert s2.size() == 1; - assert !s2.isEmpty(); + // remove + Set s2 = new HashSet<>(); + s2.add("1"); + assert s2.size() == 1; + assert s2.remove("1"); + assert s2.size() == 0; + s2.add("2"); + assert !s2.remove("1"); + assert s2.size() == 1; + assert !s2.isEmpty(); - Set s3 = new HashSet<>(); - s3.add(1); - assert s3.size() == 1; - assert s3.remove(1); - assert s3.size() == 0; - s3.add(2); - assert !s3.remove(1); - assert s3.size() == 1; + Set s3 = new HashSet<>(); + s3.add(1); + assert s3.size() == 1; + assert s3.remove(1); + assert s3.size() == 0; + s3.add(2); + assert !s3.remove(1); + assert s3.size() == 1; - // contains - Set s4A = new HashSet<>(); - Set s4B = new HashSet<>(); - Set s4C = new HashSet<>(); - Set> s4 = new HashSet<>(); - s4.add(s4A); - s4.add(s4B); - assert s4.size() == 2; - assert s4.contains(s4A); - assert s4.contains(s4B); - assert !s4.contains(s4C); + // contains + Set s4A = new HashSet<>(); + Set s4B = new HashSet<>(); + Set s4C = new HashSet<>(); + Set> s4 = new HashSet<>(); + s4.add(s4A); + s4.add(s4B); + assert s4.size() == 2; + assert s4.contains(s4A); + assert s4.contains(s4B); + assert !s4.contains(s4C); - // addAll - Set s5A = new HashSet<>(); - s5A.add("1"); - s5A.add("2"); - Set s5B = new HashSet<>(); - s5B.add("3"); - s5B.add("4"); - Set s5Merged = new HashSet<>(); - boolean addedAll = s5Merged.addAll(s5A); - assert addedAll; - s5Merged.addAll(s5B); - assert s5Merged.size() == 4; - for (int i = 1; i <= 4; i++) { - assert s5Merged.contains("" + i); - } + // addAll + Set s5A = new HashSet<>(); + s5A.add("1"); + s5A.add("2"); + Set s5B = new HashSet<>(); + s5B.add("3"); + s5B.add("4"); + Set s5Merged = new HashSet<>(); + boolean addedAll = s5Merged.addAll(s5A); + assert addedAll; + s5Merged.addAll(s5B); + assert s5Merged.size() == 4; + for (int i = 1; i <= 4; i++) { + assert s5Merged.contains("" + i); + } - // new HashSet(Collection<>); - Set s6A = new HashSet<>(); - s6A.add("1"); - s6A.add("2"); - Set s6 = new HashSet<>(s6A); - assert s6.size() == 2; - for (int i = 1; i <= 2; i++) { - assert s6.contains("" + i); - } + // new HashSet(Collection<>); + Set s6A = new HashSet<>(); + s6A.add("1"); + s6A.add("2"); + Set s6 = new HashSet<>(s6A); + assert s6.size() == 2; + for (int i = 1; i <= 2; i++) { + assert s6.contains("" + i); + } - // new HashSet(int initialCapacity); - Set s7 = new HashSet<>(10); - assert s7.size() == 0; - assert s7.isEmpty(); + // new HashSet(int initialCapacity); + Set s7 = new HashSet<>(10); + assert s7.size() == 0; + assert s7.isEmpty(); - // new HashSet(int initialCapacity, float loadFactor); - Set s8 = new HashSet<>(10, 11); - assert s8.size() == 0; - assert s8.isEmpty(); + // new HashSet(int initialCapacity, float loadFactor); + Set s8 = new HashSet<>(10, 11); + assert s8.size() == 0; + assert s8.isEmpty(); - // removeAll - Set s9A = new HashSet<>(); - s9A.add("1"); - s9A.add("3"); - s9A.add("5"); - s9A.add("7"); - Set s9 = new HashSet<>(); - s9.add("1"); - s9.add("2"); - s9.add("3"); - s9.add("4"); - s9.add("5"); - assert s9.size() == 5; - boolean removedAll = s9.removeAll(s9A); - assert removedAll; - assert s9.size() == 2; - assert s9.contains("2"); - assert !s9.contains("3"); - assert s9.contains("4"); + // removeAll + Set s9A = new HashSet<>(); + s9A.add("1"); + s9A.add("3"); + s9A.add("5"); + s9A.add("7"); + Set s9 = new HashSet<>(); + s9.add("1"); + s9.add("2"); + s9.add("3"); + s9.add("4"); + s9.add("5"); + assert s9.size() == 5; + boolean removedAll = s9.removeAll(s9A); + assert removedAll; + assert s9.size() == 2; + assert s9.contains("2"); + assert !s9.contains("3"); + assert s9.contains("4"); - // retainAll - Set s10A = new HashSet<>(); - s10A.add("1"); - s10A.add("3"); - s10A.add("5"); - s10A.add("7"); - Set s10 = new HashSet<>(); - s10.add("1"); - s10.add("2"); - s10.add("3"); - s10.add("4"); - s10.add("5"); - assert s10.size() == 5; - boolean retainedAll = s10.retainAll(s10A); - assert retainedAll; - assert s10.size() == 3; - assert s10.contains("1"); - assert !s10.contains("2"); - assert s10.contains("3"); - assert !s10.contains("4"); - assert s10.contains("5"); - assert !s10.contains("7"); + // retainAll + Set s10A = new HashSet<>(); + s10A.add("1"); + s10A.add("3"); + s10A.add("5"); + s10A.add("7"); + Set s10 = new HashSet<>(); + s10.add("1"); + s10.add("2"); + s10.add("3"); + s10.add("4"); + s10.add("5"); + assert s10.size() == 5; + boolean retainedAll = s10.retainAll(s10A); + assert retainedAll; + assert s10.size() == 3; + assert s10.contains("1"); + assert !s10.contains("2"); + assert s10.contains("3"); + assert !s10.contains("4"); + assert s10.contains("5"); + assert !s10.contains("7"); - // toArray - Set s11 = new HashSet<>(); - s11.add("1"); - s11.add("2"); - String[] ar = (String[]) s11.toArray(); - assert ar.length == 2; - assert "1".equals(ar[0]) || "2".equals(ar[0]); - assert "1".equals(ar[1]) || "2".equals(ar[1]); - assert !ar[0].equals(ar[1]); - } + // toArray + Set s11 = new HashSet<>(); + s11.add("1"); + s11.add("2"); + String[] ar = (String[]) s11.toArray(); + assert ar.length == 2; + assert "1".equals(ar[0]) || "2".equals(ar[0]); + assert "1".equals(ar[1]) || "2".equals(ar[1]); + assert !ar[0].equals(ar[1]); + + // forEach + List iterated = new ArrayList<>(); + s11.forEach(str -> iterated.add(str)); + assert iterated.size() == 2; + assert iterated.get(0) == "1"; + assert iterated.get(1) == "2"; + } }