From ad3f4357c5d58a1a6ca095fa7ea12616a6728d0f Mon Sep 17 00:00:00 2001 From: Louis Grignon Date: Mon, 28 Sep 2020 15:23:44 +0200 Subject: [PATCH 1/3] fix #613 Optional support --- .../org/jsweet/transpiler/JSweetContext.java | 3 + .../extension/Java2TypeScriptAdapter.java | 14 +- .../RemoveJavaDependenciesAdapter.java | 3322 +++++++++-------- .../transpiler/model/support/UtilSupport.java | 6 + transpiler/src/test/java/.gitignore | 1 + .../org/jsweet/test/transpiler/ApiTests.java | 417 ++- .../src/test/java/source/api/Optionals.java | 103 + 7 files changed, 2036 insertions(+), 1830 deletions(-) create mode 100644 transpiler/src/test/java/.gitignore create mode 100644 transpiler/src/test/java/source/api/Optionals.java diff --git a/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java b/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java index 273830d1..2a361ec1 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java @@ -1947,4 +1947,7 @@ public class JSweetContext extends Context { } } + public Elements elements() { + return JavacElements.instance(this); + } } \ No newline at end of file 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 0d0d5b27..cfe462c5 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/extension/Java2TypeScriptAdapter.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/extension/Java2TypeScriptAdapter.java @@ -1315,11 +1315,8 @@ public class Java2TypeScriptAdapter extends PrinterAdapter { print(")"); } } else { - printMacroName(targetMethodName); - print("(((o1: any, o2: any) => { if(o1 && o1.equals) { return o1.equals(o2); } else { return o1 === o2; } })("); - printTarget(invocationElement.getTargetExpression()).print(",") - .print(invocationElement.getArgument(0)); - print("))"); + printDefaultEquals(invocationElement.getTargetExpression(), + invocationElement.getArgument(0)); } return true; case "compareTo": @@ -1412,6 +1409,12 @@ public class Java2TypeScriptAdapter extends PrinterAdapter { .print(target).print(")"); } } + + protected void printDefaultEquals(ExtendedElement left, ExtendedElement right) { + print("(((o1: any, o2: any) => o1 && o1.equals ? o1.equals(o2) : o1 === o2)("); + printTarget(left).print(",").print(right); + print("))"); + } protected void printFunctionalInvocation2(ExtendedElement target, String functionName, List arguments) { @@ -1677,4 +1680,5 @@ public class Java2TypeScriptAdapter extends PrinterAdapter { return super.substituteForEachLoop(foreachLoop, targetHasLength, indexVarName); } + } diff --git a/transpiler/src/main/java/org/jsweet/transpiler/extension/RemoveJavaDependenciesAdapter.java b/transpiler/src/main/java/org/jsweet/transpiler/extension/RemoveJavaDependenciesAdapter.java index d764bd09..4e0069b7 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/extension/RemoveJavaDependenciesAdapter.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/extension/RemoveJavaDependenciesAdapter.java @@ -52,6 +52,7 @@ import java.util.List; import java.util.ListIterator; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.Properties; import java.util.Queue; import java.util.Set; @@ -97,1689 +98,1774 @@ import com.sun.tools.javac.tree.JCTree.JCTypeApply; */ public class RemoveJavaDependenciesAdapter extends Java2TypeScriptAdapter { - protected Map extTypesMapping = new HashMap<>(); - private final String ERASED_CLASS_HIERARCHY_FIELD = "__classes"; - private Set excludedJavaSuperTypes = new HashSet<>(); + protected Map extTypesMapping = new HashMap<>(); + private final String ERASED_CLASS_HIERARCHY_FIELD = "__classes"; + private Set excludedJavaSuperTypes = new HashSet<>(); - public RemoveJavaDependenciesAdapter(JSweetContext context) { - super(context); - init(); - } - - public RemoveJavaDependenciesAdapter(PrinterAdapter parentAdapter) { - super(parentAdapter); - init(); - } - - protected void init() { - initTypesMapping(); - addTypeMappings(extTypesMapping); + public RemoveJavaDependenciesAdapter(JSweetContext context) { + super(context); + init(); } - protected void initTypesMapping() { - addTypeMapping(Class.class.getName(), "any"); - context.getLangTypeMappings().put(RuntimeException.class.getName(), "Error"); - context.getBaseThrowables().add(RuntimeException.class.getName()); + public RemoveJavaDependenciesAdapter(PrinterAdapter parentAdapter) { + super(parentAdapter); + init(); + } - extTypesMapping.put(URL.class.getName(), "URL"); - extTypesMapping.put(List.class.getName(), "Array"); - extTypesMapping.put(AbstractList.class.getName(), "Array"); - extTypesMapping.put(ArrayList.class.getName(), "Array"); - extTypesMapping.put(Iterable.class.getName(), "Array"); - extTypesMapping.put(LinkedList.class.getName(), "Array"); - extTypesMapping.put(Collection.class.getName(), "Array"); - extTypesMapping.put(Set.class.getName(), "Array"); - extTypesMapping.put(EnumSet.class.getName(), "Array"); - extTypesMapping.put(Deque.class.getName(), "Array"); - extTypesMapping.put(Queue.class.getName(), "Array"); - extTypesMapping.put(Stack.class.getName(), "Array"); - extTypesMapping.put(HashSet.class.getName(), "Array"); - extTypesMapping.put(TreeSet.class.getName(), "Array"); - extTypesMapping.put(Vector.class.getName(), "Array"); - extTypesMapping.put(Enumeration.class.getName(), "any"); - extTypesMapping.put(Iterator.class.getName(), "any"); - extTypesMapping.put(ListIterator.class.getName(), "any"); - extTypesMapping.put(Map.class.getName(), "any"); - extTypesMapping.put(Properties.class.getName(), "any"); - extTypesMapping.put(AbstractMap.class.getName(), "any"); - extTypesMapping.put(HashMap.class.getName(), "any"); - extTypesMapping.put(TreeMap.class.getName(), "any"); - extTypesMapping.put(WeakHashMap.class.getName(), "any"); - extTypesMapping.put(LinkedHashMap.class.getName(), "any"); - extTypesMapping.put(Hashtable.class.getName(), "any"); - extTypesMapping.put(Comparator.class.getName(), "any"); - extTypesMapping.put(Exception.class.getName(), "Error"); - extTypesMapping.put(RuntimeException.class.getName(), "Error"); - extTypesMapping.put(Throwable.class.getName(), "Error"); - extTypesMapping.put(Error.class.getName(), "Error"); - extTypesMapping.put(StringBuffer.class.getName(), "{ str: string, toString: Function }"); - extTypesMapping.put(StringBuilder.class.getName(), "{ str: string, toString: Function }"); - extTypesMapping.put(Collator.class.getName(), "any"); - extTypesMapping.put(Calendar.class.getName(), "Date"); - extTypesMapping.put(GregorianCalendar.class.getName(), "Date"); - extTypesMapping.put(TimeZone.class.getName(), "string"); - extTypesMapping.put(Locale.class.getName(), "string"); - extTypesMapping.put(Charset.class.getName(), "string"); - extTypesMapping.put(Reader.class.getName(), "{ str: string, cursor: number }"); - extTypesMapping.put(StringReader.class.getName(), "{ str: string, cursor: number }"); - extTypesMapping.put(InputStream.class.getName(), "{ str: string, cursor: number }"); - extTypesMapping.put(InputStreamReader.class.getName(), "{ str: string, cursor: number }"); - extTypesMapping.put(BufferedReader.class.getName(), "{ str: string, cursor: number }"); + protected void init() { + initTypesMapping(); + addTypeMappings(extTypesMapping); + } - extTypesMapping.put(Method.class.getName(), "{ owner: any, name: string, fn : Function }"); + protected void initTypesMapping() { + addTypeMapping(Class.class.getName(), "any"); + context.getLangTypeMappings().put(RuntimeException.class.getName(), "Error"); + context.getBaseThrowables().add(RuntimeException.class.getName()); - addTypeMapping( - (typeTree, - name) -> name.startsWith("java.") - && types().isSubtype(typeTree.getType(), util().getType(Throwable.class)) ? "Error" - : null); - // TODO: use standard API - // addTypeMapping((typeTree, - // name) -> typeTree.asType() instanceof DeclaredType - // && - // WeakReference.class.getName().equals(types().getQualifiedName(typeTree.asType())) - // ? ((DeclaredType) typeTree.asType()).getTypeArguments().get(0) : - // null); - addTypeMapping((typeTree, - name) -> ExtendedElementFactory.toTree(typeTree) instanceof JCTypeApply && WeakReference.class.getName() - .equals(ExtendedElementFactory.toTree(typeTree).type.tsym.getQualifiedName().toString()) - ? ((JCTypeApply) ExtendedElementFactory.toTree(typeTree)).arguments.head - : null); - excludedJavaSuperTypes.add(EventObject.class.getName()); - } + extTypesMapping.put(URL.class.getName(), "URL"); + extTypesMapping.put(List.class.getName(), "Array"); + extTypesMapping.put(AbstractList.class.getName(), "Array"); + extTypesMapping.put(ArrayList.class.getName(), "Array"); + extTypesMapping.put(Iterable.class.getName(), "Array"); + extTypesMapping.put(LinkedList.class.getName(), "Array"); + extTypesMapping.put(Collection.class.getName(), "Array"); + extTypesMapping.put(Set.class.getName(), "Array"); + extTypesMapping.put(EnumSet.class.getName(), "Array"); + extTypesMapping.put(Deque.class.getName(), "Array"); + extTypesMapping.put(Queue.class.getName(), "Array"); + extTypesMapping.put(Stack.class.getName(), "Array"); + extTypesMapping.put(HashSet.class.getName(), "Array"); + extTypesMapping.put(TreeSet.class.getName(), "Array"); + extTypesMapping.put(Vector.class.getName(), "Array"); + extTypesMapping.put(Enumeration.class.getName(), "any"); + extTypesMapping.put(Iterator.class.getName(), "any"); + extTypesMapping.put(ListIterator.class.getName(), "any"); + extTypesMapping.put(Map.class.getName(), "any"); + extTypesMapping.put(Properties.class.getName(), "any"); + extTypesMapping.put(AbstractMap.class.getName(), "any"); + extTypesMapping.put(HashMap.class.getName(), "any"); + extTypesMapping.put(TreeMap.class.getName(), "any"); + extTypesMapping.put(WeakHashMap.class.getName(), "any"); + extTypesMapping.put(LinkedHashMap.class.getName(), "any"); + extTypesMapping.put(Hashtable.class.getName(), "any"); + extTypesMapping.put(Comparator.class.getName(), "any"); + extTypesMapping.put(Exception.class.getName(), "Error"); + extTypesMapping.put(RuntimeException.class.getName(), "Error"); + extTypesMapping.put(Throwable.class.getName(), "Error"); + extTypesMapping.put(Error.class.getName(), "Error"); + extTypesMapping.put(StringBuffer.class.getName(), "{ str: string, toString: Function }"); + extTypesMapping.put(StringBuilder.class.getName(), "{ str: string, toString: Function }"); + extTypesMapping.put(Collator.class.getName(), "any"); + extTypesMapping.put(Calendar.class.getName(), "Date"); + extTypesMapping.put(GregorianCalendar.class.getName(), "Date"); + extTypesMapping.put(TimeZone.class.getName(), "string"); + extTypesMapping.put(Locale.class.getName(), "string"); + extTypesMapping.put(Charset.class.getName(), "string"); + extTypesMapping.put(Reader.class.getName(), "{ str: string, cursor: number }"); + extTypesMapping.put(StringReader.class.getName(), "{ str: string, cursor: number }"); + extTypesMapping.put(InputStream.class.getName(), "{ str: string, cursor: number }"); + extTypesMapping.put(InputStreamReader.class.getName(), "{ str: string, cursor: number }"); + extTypesMapping.put(BufferedReader.class.getName(), "{ str: string, cursor: number }"); - @Override - public String needsImport(ImportElement importElement, String qualifiedName) { - if (isJDKPath(qualifiedName)) { - return null; - } - return super.needsImport(importElement, qualifiedName); - } + extTypesMapping.put(Method.class.getName(), "{ owner: any, name: string, fn : Function }"); - protected RemoveJavaDependenciesAdapter print(ExtendedElement expression, boolean delegate) { - if (delegate) { - print("(").print(expression).print(").__delegate"); - } else { - print(expression); - } - delegate = false; - return this; - } + addTypeMapping((ExtendedElement typeElement, String qualifiedName) -> { + TypeMirror type = typeElement.getType(); + if (!qualifiedName.startsWith("java.") || type == null) { + return null; + } - protected RemoveJavaDependenciesAdapter printTargetForParameter(ExtendedElement expression, boolean delegate) { - if (expression != null && expression.toString().equals("super")) { - getPrinter().print("this"); - return this; - } + // Throwable + if (types().isSubtype(type, util().getType(Throwable.class))) { + return "Error"; + } - return print(expression, delegate); - } + // Optional + if (types().isSubtype(types().erasure(type), types().erasure(util().getType(Optional.class))) + && type instanceof DeclaredType) { + List typeArgs = ((DeclaredType) type).getTypeArguments(); + if (typeArgs.size() > 0) { + return getMappedType(typeArgs.get(0)); + } + } - @Override - public boolean substituteMethodInvocation(MethodInvocationElement invocation) { - String targetMethodName = invocation.getMethodName(); - String targetClassName = invocation.getMethod().getEnclosingElement().toString(); - ExtendedElement targetExpression = invocation.getTargetExpression(); - if (targetExpression != null) { - targetClassName = targetExpression.getTypeAsElement().toString(); - } - TypeMirror jdkSuperclass = context.getJdkSuperclass(targetClassName, excludedJavaSuperTypes); - boolean delegate = jdkSuperclass != null; - if (delegate) { - targetClassName = jdkSuperclass.toString(); - } + return null; + }); + + // TODO: use standard API + // addTypeMapping((typeTree, + // name) -> typeTree.asType() instanceof DeclaredType + // && + // WeakReference.class.getName().equals(types().getQualifiedName(typeTree.asType())) + // ? ((DeclaredType) typeTree.asType()).getTypeArguments().get(0) : + // null); + addTypeMapping((typeTree, + name) -> ExtendedElementFactory.toTree(typeTree) instanceof JCTypeApply && WeakReference.class.getName() + .equals(ExtendedElementFactory.toTree(typeTree).type.tsym.getQualifiedName().toString()) + ? ((JCTypeApply) ExtendedElementFactory.toTree(typeTree)).arguments.head + : null); + excludedJavaSuperTypes.add(EventObject.class.getName()); + } - if (targetClassName != null - && (targetExpression != null || invocation.getMethod().getModifiers().contains(Modifier.STATIC))) { - switch (targetClassName) { + @Override + public String needsImport(ImportElement importElement, String qualifiedName) { + if (isJDKPath(qualifiedName)) { + return null; + } + return super.needsImport(importElement, qualifiedName); + } - case "java.lang.Float": - case "java.lang.Double": - case "java.lang.Integer": - case "java.lang.Byte": - case "java.lang.Long": - case "java.lang.Short": - if (substituteMethodInvocationOnNumber(invocation, targetMethodName)) { - return true; - } - break; - case "java.lang.Character": - if (substituteMethodInvocationOnCharacter(invocation, targetMethodName)) { - return true; - } - break; - case "java.util.Collection": - case "java.util.List": - case "java.util.AbstractList": - case "java.util.AbstractSet": - case "java.util.AbstractCollection": - case "java.util.Queue": - case "java.util.Deque": - case "java.util.LinkedList": - case "java.util.ArrayList": - case "java.util.Stack": - case "java.util.Vector": - case "java.util.Set": - case "java.util.EnumSet": - case "java.util.HashSet": - case "java.util.TreeSet": - if (substituteMethodInvocationOnArray(invocation, targetMethodName, targetClassName, delegate)) { - return true; - } - break; + protected RemoveJavaDependenciesAdapter print(ExtendedElement expression, boolean delegate) { + if (delegate) { + print("(").print(expression).print(").__delegate"); + } else { + print(expression); + } + delegate = false; + return this; + } - case "java.util.Properties": - case "java.util.Dictionary": - case "java.util.Map": - case "java.util.AbstractMap": - case "java.util.HashMap": - case "java.util.TreeMap": - case "java.util.Hashtable": - case "java.util.WeakHashMap": - case "java.util.LinkedHashMap": - if (substituteMethodInvocationOnMap(invocation, targetMethodName, targetExpression, delegate)) { - return true; - } - break; - case "java.util.Collections": - if (substituteMethodInvocationOnCollections(invocation, targetMethodName, targetExpression, delegate)) { - return true; - } - break; - case "java.util.Arrays": - if (substituteMethodInvocationOnArrays(invocation, targetMethodName, targetExpression, delegate)) { - return true; - } - break; - case "java.lang.System": - switch (targetMethodName) { - case "arraycopy": - printMacroName(targetMethodName); - print("((srcPts, srcOff, dstPts, dstOff, size) => { if(srcPts !== dstPts || dstOff >= srcOff + size) { while (--size >= 0) dstPts[dstOff++] = srcPts[srcOff++];" - + "} else { let tmp = srcPts.slice(srcOff, srcOff + size); for (let i = 0; i < size; i++) dstPts[dstOff++] = tmp[i]; }})(") - .printArgList(invocation.getArguments()).print(")"); - return true; - case "currentTimeMillis": - printMacroName(targetMethodName); - print("Date.now()"); - return true; - case "nanoTime": - printMacroName(targetMethodName); - print("(Date.now() * 1000000)"); - return true; - } - break; + protected RemoveJavaDependenciesAdapter printTargetForParameter(ExtendedElement expression, boolean delegate) { + if (expression != null && expression.toString().equals("super")) { + getPrinter().print("this"); + return this; + } - case "java.util.Objects": - if (substituteMethodInvocationOnObjects(invocation, targetMethodName, delegate)) { - return true; - } - break; - case "java.lang.StringBuffer": - case "java.lang.StringBuilder": - if (substituteMethodInvocationOnStringBuilder(invocation, targetMethodName, delegate)) { - return true; - } - break; - case "java.lang.ref.WeakReference": - switch (targetMethodName) { - case "get": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate); - return true; - } - break; - case "java.text.Collator": - switch (targetMethodName) { - case "getInstance": - printMacroName(targetMethodName); - print("{ compare: (o1, o2) => o1.toString().localeCompare(o2.toString()), equals: (o1, o2) => o1.toString().localeCompare(o2.toString()) === 0 }"); - return true; - } - break; - case "java.nio.charset.Charset": - switch (targetMethodName) { - case "forName": - print(invocation.getArgument(0)); - return true; - } - break; - case "java.util.Locale": - switch (targetMethodName) { - case "getDefault": - printMacroName(targetMethodName); - getPrinter().print("(window.navigator['userLanguage'] || window.navigator.language)"); - return true; - } - break; - case "java.util.TimeZone": - switch (targetMethodName) { - case "getTimeZone": - if (invocation.getArgumentCount() == 1) { - printMacroName(targetMethodName); - print(invocation.getArgument(0)); - return true; - } - break; - case "getDefault": - printMacroName(targetMethodName); - getPrinter().print("\"UTC\""); - return true; - case "getID": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate); - return true; - } - break; - case "java.util.Calendar": - case "java.util.GregorianCalendar": - if (substituteMethodInvocationOnCalendar(invocation, targetMethodName, delegate)) { - return true; - } - break; + return print(expression, delegate); + } - case "java.io.Reader": - case "java.io.StringReader": - case "java.io.InputStream": - case "java.io.InputStreamReader": - case "java.io.BufferedReader": - switch (targetMethodName) { - case "read": - printMacroName(targetMethodName); - print("(r => r.str.charCodeAt(r.cursor++))("); - print(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "skip": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".cursor+=") - .print(invocation.getArgument(0)); - return true; - case "reset": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".cursor=0"); - return true; - case "close": - printMacroName(targetMethodName); - // ignore but we could flag it and throw an error... - return true; - } - break; - case "java.lang.ThreadLocal": - switch (targetMethodName) { - case "get": - printMacroName(targetMethodName); + @Override + public boolean substituteMethodInvocation(MethodInvocationElement invocation) { + String targetMethodName = invocation.getMethodName(); + String targetClassName = invocation.getMethod().getEnclosingElement().toString(); + ExtendedElement targetExpression = invocation.getTargetExpression(); + if (targetExpression != null) { + targetClassName = targetExpression.getTypeAsElement().toString(); + } + TypeMirror jdkSuperclass = context.getJdkSuperclass(targetClassName, excludedJavaSuperTypes); + boolean delegate = jdkSuperclass != null; + if (delegate) { + targetClassName = jdkSuperclass.toString(); + } - print("((tlObj: any) => {" // - + " if (tlObj.___value) { return tlObj.___value } " // - + " else { return tlObj.___value = tlObj.initialValue() } " // - + " })("); - print(invocation.getTargetExpression()); - print(")"); - return true; - } - break; + if (targetClassName != null + && (targetExpression != null || invocation.getMethod().getModifiers().contains(Modifier.STATIC))) { + switch (targetClassName) { - case "java.lang.Class": - if (substituteMethodInvocationOnClass(invocation, targetMethodName, delegate)) { - return true; - } - break; + case "java.lang.Float": + case "java.lang.Double": + case "java.lang.Integer": + case "java.lang.Byte": + case "java.lang.Long": + case "java.lang.Short": + if (substituteMethodInvocationOnNumber(invocation, targetMethodName)) { + return true; + } + break; + case "java.lang.Character": + if (substituteMethodInvocationOnCharacter(invocation, targetMethodName)) { + return true; + } + break; + case "java.util.Collection": + case "java.util.List": + case "java.util.AbstractList": + case "java.util.AbstractSet": + case "java.util.AbstractCollection": + case "java.util.Queue": + case "java.util.Deque": + case "java.util.LinkedList": + case "java.util.ArrayList": + case "java.util.Stack": + case "java.util.Vector": + case "java.util.Set": + case "java.util.EnumSet": + case "java.util.HashSet": + case "java.util.TreeSet": + if (substituteMethodInvocationOnArray(invocation, targetMethodName, targetClassName, delegate)) { + return true; + } + break; - case "java.lang.reflect.Method": - if (substituteMethodInvocationOnMethod(invocation, targetMethodName, delegate)) { - return true; - } - break; + case "java.util.Properties": + case "java.util.Dictionary": + case "java.util.Map": + case "java.util.AbstractMap": + case "java.util.HashMap": + case "java.util.TreeMap": + case "java.util.Hashtable": + case "java.util.WeakHashMap": + case "java.util.LinkedHashMap": + if (substituteMethodInvocationOnMap(invocation, targetMethodName, targetExpression, delegate)) { + return true; + } + break; + case "java.util.Collections": + if (substituteMethodInvocationOnCollections(invocation, targetMethodName, targetExpression, delegate)) { + return true; + } + break; + case "java.util.Arrays": + if (substituteMethodInvocationOnArrays(invocation, targetMethodName, targetExpression, delegate)) { + return true; + } + break; + case "java.lang.System": + switch (targetMethodName) { + case "arraycopy": + printMacroName(targetMethodName); + print("((srcPts, srcOff, dstPts, dstOff, size) => { if(srcPts !== dstPts || dstOff >= srcOff + size) { while (--size >= 0) dstPts[dstOff++] = srcPts[srcOff++];" + + "} else { let tmp = srcPts.slice(srcOff, srcOff + size); for (let i = 0; i < size; i++) dstPts[dstOff++] = tmp[i]; }})(") + .printArgList(invocation.getArguments()).print(")"); + return true; + case "currentTimeMillis": + printMacroName(targetMethodName); + print("Date.now()"); + return true; + case "nanoTime": + printMacroName(targetMethodName); + print("(Date.now() * 1000000)"); + return true; + } + break; - case "java.lang.reflect.Field": - if (substituteMethodInvocationOnField(invocation, targetMethodName, delegate)) { - return true; - } - break; + case "java.util.Objects": + if (substituteMethodInvocationOnObjects(invocation, targetMethodName, delegate)) { + return true; + } + break; + case "java.util.Optional": + if (substituteMethodInvocationOnOptional(invocation, targetMethodName, delegate)) { + return true; + } + break; + case "java.lang.StringBuffer": + case "java.lang.StringBuilder": + if (substituteMethodInvocationOnStringBuilder(invocation, targetMethodName, delegate)) { + return true; + } + break; + case "java.lang.ref.WeakReference": + switch (targetMethodName) { + case "get": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate); + return true; + } + break; + case "java.text.Collator": + switch (targetMethodName) { + case "getInstance": + printMacroName(targetMethodName); + print("{ compare: (o1, o2) => o1.toString().localeCompare(o2.toString()), equals: (o1, o2) => o1.toString().localeCompare(o2.toString()) === 0 }"); + return true; + } + break; + case "java.nio.charset.Charset": + switch (targetMethodName) { + case "forName": + print(invocation.getArgument(0)); + return true; + } + break; + case "java.util.Locale": + switch (targetMethodName) { + case "getDefault": + printMacroName(targetMethodName); + getPrinter().print("(window.navigator['userLanguage'] || window.navigator.language)"); + return true; + } + break; + case "java.util.TimeZone": + switch (targetMethodName) { + case "getTimeZone": + if (invocation.getArgumentCount() == 1) { + printMacroName(targetMethodName); + print(invocation.getArgument(0)); + return true; + } + break; + case "getDefault": + printMacroName(targetMethodName); + getPrinter().print("\"UTC\""); + return true; + case "getID": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate); + return true; + } + break; + case "java.util.Calendar": + case "java.util.GregorianCalendar": + if (substituteMethodInvocationOnCalendar(invocation, targetMethodName, delegate)) { + return true; + } + break; - case "java.lang.reflect.Array": - switch (targetMethodName) { - case "newInstance": - printMacroName(targetMethodName); - if (invocation.getArgumentCount() == 2) { - print("new Array(").print(invocation.getArgument(1)).print(")"); - return true; - } - case "getLength": - printMacroName(targetMethodName); - print(invocation.getArgument(0)).print(".length"); - return true; - case "get": - printMacroName(targetMethodName); - print(invocation.getArgument(0)).print("[").print(invocation.getArgument(1)).print("]"); - return true; - case "set": - printMacroName(targetMethodName); - print("(").print(invocation.getArgument(0)).print("[").print(invocation.getArgument(1)).print("]=") - .print(invocation.getArgument(1)).print(")"); - return true; - } - break; + case "java.io.Reader": + case "java.io.StringReader": + case "java.io.InputStream": + case "java.io.InputStreamReader": + case "java.io.BufferedReader": + switch (targetMethodName) { + case "read": + printMacroName(targetMethodName); + print("(r => r.str.charCodeAt(r.cursor++))("); + print(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "skip": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".cursor+=") + .print(invocation.getArgument(0)); + return true; + case "reset": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".cursor=0"); + return true; + case "close": + printMacroName(targetMethodName); + // ignore but we could flag it and throw an error... + return true; + } + break; + case "java.lang.ThreadLocal": + switch (targetMethodName) { + case "get": + printMacroName(targetMethodName); - case "java.lang.Math": - case "java.lang.StrictMath": - switch (targetMethodName) { - case "ulp": - printMacroName(targetMethodName); - print("((x) => { let buffer = new ArrayBuffer(8); let dataView = new DataView(buffer); dataView.setFloat64(0, x); let first = dataView.getUint32(0); let second = dataView.getUint32(4); let rawExponent = first & 0x7ff00000; if (rawExponent == 0x7ff00000) { dataView.setUint32(0,first & 0x7fffffff); } else if (rawExponent == 0) { dataView.setUint32(4,1); dataView.setUint32(0,0); } else if (rawExponent >= (52 << 20) + 0x00100000) { dataView.setUint32(0,rawExponent - (52 << 20)); dataView.setUint32(4,0); } else if (rawExponent >= (33 << 20)) { dataView.setUint32(0,1 << ((rawExponent - (33 << 20)) >>> 20 )); dataView.setUint32(4,0); } else { dataView.setUint32(4,1 << ((rawExponent - 0x00100000) >>> 20)); dataView.setUint32(0,0); } return dataView.getFloat64(0); })(") - .printArgList(invocation.getArguments()).print(")"); - return true; - case "IEEEremainder": - printMacroName(targetMethodName); - // credits: Ray Cromwell - print("((f1, f2) => { let r = Math.abs(f1 % f2); if (isNaN(r) || r == f2 || r <= Math.abs(f2) / 2.0) { return r; } else { return (f1 > 0 ? 1 : -1) * (r - f2); } })(") - .printArgList(invocation.getArguments()).print(")"); - return true; - } - } + print("((tlObj: any) => {" // + + " if (tlObj.___value) { return tlObj.___value } " // + + " else { return tlObj.___value = tlObj.initialValue() } " // + + " })("); + print(invocation.getTargetExpression()); + print(")"); + return true; + } + break; - switch (targetMethodName) { - case "clone": - printMacroName(targetMethodName); - if (targetExpression != null && invocation.getTargetExpression().getType() instanceof ArrayType) { - print(invocation.getTargetExpression(), delegate).print(".slice(0)"); - return true; - } - break; - } + case "java.lang.Class": + if (substituteMethodInvocationOnClass(invocation, targetMethodName, delegate)) { + return true; + } + break; - } + case "java.lang.reflect.Method": + if (substituteMethodInvocationOnMethod(invocation, targetMethodName, delegate)) { + return true; + } + break; - return super.substituteMethodInvocation(invocation); - } + case "java.lang.reflect.Field": + if (substituteMethodInvocationOnField(invocation, targetMethodName, delegate)) { + return true; + } + break; - protected boolean substituteMethodInvocationOnObjects(MethodInvocationElement invocation, String targetMethodName, - boolean delegate) { - switch (targetMethodName) { - case "hash": - printMacroName(targetMethodName); - print("0"); - return true; - case "requireNonNull": - printMacroName(targetMethodName); - print("if(").print(invocation.getArgument(0)).print("==null){throw new Error('cannot be null')}"); - return true; - } - return false; - } + case "java.lang.reflect.Array": + switch (targetMethodName) { + case "newInstance": + printMacroName(targetMethodName); + if (invocation.getArgumentCount() == 2) { + print("new Array(").print(invocation.getArgument(1)).print(")"); + return true; + } + case "getLength": + printMacroName(targetMethodName); + print(invocation.getArgument(0)).print(".length"); + return true; + case "get": + printMacroName(targetMethodName); + print(invocation.getArgument(0)).print("[").print(invocation.getArgument(1)).print("]"); + return true; + case "set": + printMacroName(targetMethodName); + print("(").print(invocation.getArgument(0)).print("[").print(invocation.getArgument(1)).print("]=") + .print(invocation.getArgument(1)).print(")"); + return true; + } + break; - protected boolean substituteMethodInvocationOnField(MethodInvocationElement invocation, String targetMethodName, - boolean delegate) { - switch (targetMethodName) { - case "getName": - printMacroName(targetMethodName); - print(invocation.getTargetExpression()).print(".name"); - return true; - case "get": - printMacroName(targetMethodName); - print(invocation.getArgument(0)).print("[").print(invocation.getTargetExpression()).print(".name") - .print("]"); - return true; - case "set": - printMacroName(targetMethodName); - print("(").print(invocation.getArgument(0)).print("[").print(invocation.getTargetExpression()) - .print(".name").print("]=").print(invocation.getArgument(1)).print(")"); - return true; - case "getDeclaringClass": - printMacroName(targetMethodName); - print(invocation.getTargetExpression()).print(".owner"); - return true; - case "setAccessible": - // ignore - return true; - } - return false; - } + case "java.lang.Math": + case "java.lang.StrictMath": + switch (targetMethodName) { + case "ulp": + printMacroName(targetMethodName); + print("((x) => { let buffer = new ArrayBuffer(8); let dataView = new DataView(buffer); dataView.setFloat64(0, x); let first = dataView.getUint32(0); let second = dataView.getUint32(4); let rawExponent = first & 0x7ff00000; if (rawExponent == 0x7ff00000) { dataView.setUint32(0,first & 0x7fffffff); } else if (rawExponent == 0) { dataView.setUint32(4,1); dataView.setUint32(0,0); } else if (rawExponent >= (52 << 20) + 0x00100000) { dataView.setUint32(0,rawExponent - (52 << 20)); dataView.setUint32(4,0); } else if (rawExponent >= (33 << 20)) { dataView.setUint32(0,1 << ((rawExponent - (33 << 20)) >>> 20 )); dataView.setUint32(4,0); } else { dataView.setUint32(4,1 << ((rawExponent - 0x00100000) >>> 20)); dataView.setUint32(0,0); } return dataView.getFloat64(0); })(") + .printArgList(invocation.getArguments()).print(")"); + return true; + case "IEEEremainder": + printMacroName(targetMethodName); + // credits: Ray Cromwell + print("((f1, f2) => { let r = Math.abs(f1 % f2); if (isNaN(r) || r == f2 || r <= Math.abs(f2) / 2.0) { return r; } else { return (f1 > 0 ? 1 : -1) * (r - f2); } })(") + .printArgList(invocation.getArguments()).print(")"); + return true; + } + } - protected boolean substituteMethodInvocationOnMethod(MethodInvocationElement invocation, String targetMethodName, - boolean delegate) { - switch (targetMethodName) { - case "getName": - printMacroName(targetMethodName); - print(invocation.getTargetExpression()).print(".name"); - return true; - case "invoke": - printMacroName(targetMethodName); - print(invocation.getTargetExpression()).print(".fn.apply(").print(invocation.getArgument(0)); - if (invocation.getArgumentCount() > 1) { - print(", [").printArgList(invocation.getArgumentTail()).print("]"); - } - print(")"); - return true; - case "getDeclaringClass": - printMacroName(targetMethodName); - print(invocation.getTargetExpression()).print(".owner"); - return true; - case "setAccessible": - // ignore - return true; - } - return false; - } + switch (targetMethodName) { + case "clone": + printMacroName(targetMethodName); + if (targetExpression != null && invocation.getTargetExpression().getType() instanceof ArrayType) { + print(invocation.getTargetExpression(), delegate).print(".slice(0)"); + return true; + } + break; + } - protected boolean substituteMethodInvocationOnClass(MethodInvocationElement invocation, String targetMethodName, - boolean delegate) { + } - switch (targetMethodName) { - case "forName": - printMacroName(targetMethodName); - if (getContext().options.getModuleKind() != ModuleKind.none) { - print("eval(").print(invocation.getArgument(0)).print(".split('.').slice(-1)[0])"); - } else { - print("eval(").print(invocation.getArgument(0)).print(")"); - } - return true; - case "newInstance": - printMacroName(targetMethodName); - print("new ("); - print(invocation.getTargetExpression(), delegate).print(")(").printArgList(invocation.getArguments()) - .print(")"); - return true; - case "isInstance": - printMacroName(targetMethodName); - print("((c:any,o:any) => { if(typeof c === 'string') return (o.constructor && o.constructor") - .print("[\"" + Java2TypeScriptTranslator.INTERFACES_FIELD_NAME + "\"] && o.constructor") - .print("[\"" + Java2TypeScriptTranslator.INTERFACES_FIELD_NAME + "\"].indexOf(c) >= 0) || (o") - .print("[\"" + Java2TypeScriptTranslator.INTERFACES_FIELD_NAME + "\"] && o") - .print("[\"" + Java2TypeScriptTranslator.INTERFACES_FIELD_NAME - + "\"].indexOf(c) >= 0); else if(typeof c === 'function') return (o instanceof c) || (o.constructor && o.constructor === c); })("); - print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) - .print(")"); - return true; - case "isPrimitive": - // primitive class types are never used in JSweet, so it - // will always return false - printMacroName(targetMethodName); - print("(").print(invocation.getTargetExpression()).print(" === '__erasedPrimitiveType__'").print(")"); - return true; - case "getMethods": - case "getDeclaredMethods": - printMacroName(targetMethodName); - print("(c => Object.getOwnPropertyNames(c.prototype).filter(n => typeof c.prototype[n] == 'function').map(n => ({owner:c,name:n,fn:c.prototype[n]}) ) )(") - .print(invocation.getTargetExpression()).print(")"); - return true; - case "getMethod": - case "getDeclaredMethod": - printMacroName(targetMethodName); - print("((c,p) => { if(c.prototype.hasOwnProperty(p) && typeof c.prototype[p] == 'function') return {owner:c,name:p,fn:c.prototype[p]}; else return null; })(") - .print(invocation.getTargetExpression()).print(",").print(invocation.getArgument(0)).print(")"); - return true; - case "getField": - case "getDeclaredField": - printMacroName(targetMethodName); - print("((c,p) => { return {owner:c,name:p}; })(").print(invocation.getTargetExpression()).print(",") - .print(invocation.getArgument(0)).print(")"); - return true; - } - return false; - } + return super.substituteMethodInvocation(invocation); + } - protected boolean substituteMethodInvocationOnArrays(MethodInvocationElement invocation, String targetMethodName, - ExtendedElement targetExpression, boolean delegate) { - switch (targetMethodName) { - case "asList": - printMacroName(targetMethodName); - if (invocation.getArgumentCount() == 1 && invocation.getArgument(0).getType() instanceof ArrayType) { - printArgList(invocation.getArguments()).print(".slice(0)"); - } else { - print("[").printArgList(invocation.getArguments()).print("]"); - } - return true; - case "copyOf": - printMacroName(targetMethodName); - print(invocation.getArgument(0)).print(".slice(0,").print(invocation.getArgument(1)).print(")"); - return true; - case "fill": - printMacroName(targetMethodName); - if (invocation.getArgumentCount() == 4) { - print("((a, start, end, v) => { for(let i=start;i { for(let i=0;i { if(a1==null && a2==null) return true; if(a1==null || a2==null) return false; if(a1.length != a2.length) return false; for(let i = 0; i < a1.length; i++) { if(a1[i] != a2[i]) return false; } return true; })(") - .printArgList(invocation.getArguments()).print(")"); - return true; - case "deepEquals": - printMacroName(targetMethodName); - print("(JSON.stringify(").print(invocation.getArgument(0)).print(") === JSON.stringify(") - .print(invocation.getArgument(1)).print("))"); - return true; - case "sort": - printMacroName(targetMethodName); - if (invocation.getArgumentCount() > 2) { - print("((arr, start, end, f?) => ((arr1, arr2) => arr1.splice.apply(arr1, ([start, arr2.length]).concat(arr2)))(") - .print(invocation.getArgument(0)).print(", ").print(invocation.getArgument(0)) - .print(".slice(start, end).sort(f)))(").printArgList(invocation.getArguments()).print(")"); - } else if (invocation.getArgumentCount() == 2) { - print("((l,c) => { if((c).compare) l.sort((e1,e2)=>(c).compare(e1,e2)); else l.sort(c); })(") - .print(invocation.getArgument(0)).print(",").print(invocation.getArgument(1)).print(")"); - } else { - print("((l) => {l.sort(); })(").print(invocation.getArgument(0)).print(")"); - } - return true; - } - return false; - } + private boolean substituteMethodInvocationOnOptional(MethodInvocationElement invocation, String targetMethodName, + boolean delegate) { + switch (targetMethodName) { + case "of": + print(invocation.getArgument(0)); + return true; + case "empty": + print("null"); + return true; + case "ofNullable": + print(invocation.getArgument(0)); + return true; + case "equals": + printDefaultEquals(invocation.getTargetExpression(), invocation.getArgument(0)); + return true; + case "filter": + printMacroName(targetMethodName); + print("((o, condition) => condition(o) ? o : null)(").print(invocation.getTargetExpression()).print(",") + .print(invocation.getArgument(0)).print(")"); + return true; + case "orElse": + printMacroName(targetMethodName); + print("((v, v2) => v == null ? v2 : v)(").print(invocation.getTargetExpression()).print(",") + .print(invocation.getArgument(0)).print(")"); + return true; + case "orElseGet": + case "or": + printMacroName(targetMethodName); + print("((v, get) => v == null ? get() : v)(").print(invocation.getTargetExpression()).print(",") + .print(invocation.getArgument(0)).print(")"); + return true; + case "ifPresent": + printMacroName(targetMethodName); + print("((v, action) => v != null ? action(v) : null)(").print(invocation.getTargetExpression()).print(",") + .print(invocation.getArgument(0)).print(")"); + return true; + case "ifPresentOrElse": + printMacroName(targetMethodName); + print("((v, action, fallbackAction) => v != null ? action(v) : fallbackAction())(") + .print(invocation.getTargetExpression()).print(",").print(invocation.getArgument(0)).print(",") + .print(invocation.getArgument(1)).print(")"); + return true; + case "map": + case "flatMap": + printMacroName(targetMethodName); + print("(").print(invocation.getArgument(0)).print(")(").print(invocation.getTargetExpression()).print(")"); + return true; + case "orElseThrow": + printMacroName(targetMethodName); + if (invocation.getArgumentCount() > 0) { + print("((v, throwError) => { if (v == null) throwError(); return v; })(") + .print(invocation.getTargetExpression()).print(",").print(invocation.getArgument(0)).print(")"); + } else { + print("(v => { if (v == null) throw new Error('value is null'); return v; })(") + .print(invocation.getTargetExpression()).print(")"); + } + return true; + } + return false; + } - protected boolean substituteMethodInvocationOnCollections(MethodInvocationElement invocation, - String targetMethodName, ExtendedElement targetExpression, boolean delegate) { - switch (targetMethodName) { - case "emptyList": - printMacroName(targetMethodName); - print("[]"); - return true; - case "emptySet": - printMacroName(targetMethodName); - print("[]"); - return true; - case "emptyMap": - printMacroName(targetMethodName); - print("{}"); - return true; - case "unmodifiableList": - case "unmodifiableCollection": - case "unmodifiableSet": - case "unmodifiableSortedSet": - printMacroName(targetMethodName); - printArgList(invocation.getArguments()).print(".slice(0)"); - return true; - case "singleton": - printMacroName(targetMethodName); - print("[").print(invocation.getArgument(0)).print("]"); - return true; - case "singletonList": - printMacroName(targetMethodName); - print("[").print(invocation.getArgument(0)).print("]"); - return true; - case "nCopies": - printMacroName(targetMethodName); - print("((n,v)=>{let c=[];for(let i=0;i { let o = {}; o[k] = ").print(invocation.getArgument(1)).print("; return o; })(") - .print(invocation.getArgument(0)).print(")"); - } - } else { - print("(k => { let o = {entries: [{getKey: function() { return this.key }, getValue: function() { return this.value },key:k, value:") - .print(invocation.getArgument(1)).print("}]}; return o; })(").print(invocation.getArgument(0)) - .print(")"); - } - return true; - case "binarySearch": - printMacroName(targetMethodName); - if (invocation.getArgumentCount() == 3) { - print("((l, key, c) => { let comp : any = c; if(typeof c != 'function') { comp = (a,b)=>c.compare(a,b); } let low = 0; let high = l.length-1; while (low <= high) { let mid = (low + high) >>> 1; let midVal = l[mid]; " - + "let cmp = comp(midVal, key); if (cmp < 0) low = mid + 1; else if (cmp > 0) high = mid - 1; else return mid; } " - + "return -(low + 1); })(").printArgList(invocation.getArguments()).print(")"); - return true; - } - if (invocation.getArgumentCount() == 2) { - if (util().isNumber(invocation.getArgument(1).getType())) { - print("((l, key) => { let comp = (a,b)=>a-b; let low = 0; let high = l.length-1; while (low <= high) { let mid = (low + high) >>> 1; let midVal = l[mid]; " - + "let cmp = comp(midVal, key); if (cmp < 0) low = mid + 1; else if (cmp > 0) high = mid - 1; else return mid; } " - + "return -(low + 1); })(").printArgList(invocation.getArguments()).print(")"); - return true; - } else { - print("((l, key) => { let comp = (a,b)=> {if(a.compareTo) return (a.compareTo(b)); else return a.localeCompare(b);}; let low = 0; let high = l.length-1; while (low <= high) { let mid = (low + high) >>> 1; let midVal = l[mid]; " - + "let cmp = comp(midVal, key); if (cmp < 0) low = mid + 1; else if (cmp > 0) high = mid - 1; else return mid; } " - + "return -(low + 1); })(").printArgList(invocation.getArguments()).print(")"); - return true; - } - } - case "sort": - printMacroName(targetMethodName); - if (invocation.getArgumentCount() == 2) { - print("((l,c) => { if((c).compare) l.sort((e1,e2)=>(c).compare(e1,e2)); else l.sort(c); })(") - .print(invocation.getArgument(0)).print(",").print(invocation.getArgument(1)).print(")"); - } else { - print(invocation.getArgument(0)).print(".sort(").printArgList(invocation.getArgumentTail()).print(")"); - } - return true; - case "reverse": - printMacroName(targetMethodName); - print(invocation.getArgument(0)).print(".reverse()"); - return true; - case "disjoint": - printMacroName(targetMethodName); - print("((c1, c2) => { for(let i=0;ic1[i])>=0) return false; } return true; } )(") - .printArgList(invocation.getArguments()).print(")"); - return true; - } + protected boolean substituteMethodInvocationOnObjects(MethodInvocationElement invocation, String targetMethodName, + boolean delegate) { + switch (targetMethodName) { + case "hash": + printMacroName(targetMethodName); + print("0"); + return true; + case "requireNonNull": + printMacroName(targetMethodName); + print("if(").print(invocation.getArgument(0)).print("==null){throw new Error('cannot be null')}"); + return true; + } + return false; + } - return false; - } + protected boolean substituteMethodInvocationOnField(MethodInvocationElement invocation, String targetMethodName, + boolean delegate) { + switch (targetMethodName) { + case "getName": + printMacroName(targetMethodName); + print(invocation.getTargetExpression()).print(".name"); + return true; + case "get": + printMacroName(targetMethodName); + print(invocation.getArgument(0)).print("[").print(invocation.getTargetExpression()).print(".name") + .print("]"); + return true; + case "set": + printMacroName(targetMethodName); + print("(").print(invocation.getArgument(0)).print("[").print(invocation.getTargetExpression()) + .print(".name").print("]=").print(invocation.getArgument(1)).print(")"); + return true; + case "getDeclaringClass": + printMacroName(targetMethodName); + print(invocation.getTargetExpression()).print(".owner"); + return true; + case "setAccessible": + // ignore + return true; + } + return false; + } - private boolean substituteMethodInvocationOnStringBuilder(MethodInvocationElement invocation, - String targetMethodName, boolean delegate) { - switch (targetMethodName) { - case "append": - printMacroName(targetMethodName); - if (invocation.getArgumentCount() == 1) { - print("(sb => { sb.str += ").printArgList(invocation.getArguments()) - .print("; return sb; })("); - print(invocation.getTargetExpression(), delegate).print(")"); - } else { - print("(sb => { sb.str += (").print(invocation.getArgument(0)).print(").substr(") - .printArgList(invocation.getArgumentTail()).print("); return sb; })("); - print(invocation.getTargetExpression(), delegate).print(")"); - } - return true; - case "insert": - printMacroName(targetMethodName); - print("((sb, index, c) => { sb.str = sb.str.substr(0, index) + c + sb.str.substr(index); return sb; })("); - print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) - .print(")"); - return true; - case "setCharAt": - printMacroName(targetMethodName); - print("((sb, index, c) => sb.str = sb.str.substr(0, index) + c + sb.str.substr(index + 1))("); - print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) - .print(")"); - return true; - case "deleteCharAt": - printMacroName(targetMethodName); - print("((sb, index) => { sb.str = sb.str.substr(0, index) + sb.str.substr(index + 1); return sb; })("); - print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) - .print(")"); - return true; - case "delete": - printMacroName(targetMethodName); - print("((sb, i1, i2) => { sb.str = sb.str.substr(0, i1) + sb.str.substr(i2); return sb; })("); - print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) - .print(")"); - return true; - case "length": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".str.length"); - return true; - case "charAt": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".str.charAt(").print(invocation.getArgument(0)) - .print(")"); - return true; - case "setLength": - printMacroName(targetMethodName); - print("((sb, length) => sb.str = sb.str.substring(0, length))("); - print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) - .print(")"); - return true; - case "toString": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".str"); - return true; - case "lastIndexOf": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".str.lastIndexOf(") - .print(invocation.getArgument(0)).print(")"); - return true; - case "substring": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".str.substring(") - .printArgList(invocation.getArguments()).print(")"); - return true; - } - return false; - } + protected boolean substituteMethodInvocationOnMethod(MethodInvocationElement invocation, String targetMethodName, + boolean delegate) { + switch (targetMethodName) { + case "getName": + printMacroName(targetMethodName); + print(invocation.getTargetExpression()).print(".name"); + return true; + case "invoke": + printMacroName(targetMethodName); + print(invocation.getTargetExpression()).print(".fn.apply(").print(invocation.getArgument(0)); + if (invocation.getArgumentCount() > 1) { + print(", [").printArgList(invocation.getArgumentTail()).print("]"); + } + print(")"); + return true; + case "getDeclaringClass": + printMacroName(targetMethodName); + print(invocation.getTargetExpression()).print(".owner"); + return true; + case "setAccessible": + // ignore + return true; + } + return false; + } - protected boolean substituteMethodInvocationOnCalendar(MethodInvocationElement invocation, String targetMethodName, - boolean delegate) { - switch (targetMethodName) { - case "set": - if (invocation.getArgumentCount() == 2) { - String first = invocation.getArgument(0).toString(); - if (first.endsWith("YEAR")) { - printMacroName(targetMethodName); - print("((d, p) => d[\"UTC\"]?d.setUTCFullYear(p):d.setFullYear(p))("); - print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) - .print(")"); - return true; - } else if (first.endsWith("DAY_OF_MONTH")) { - printMacroName(targetMethodName); - print("((d, p) => d[\"UTC\"]?d.setUTCDate(p):d.setDate(p))("); - print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) - .print(")"); - return true; - } else if (first.endsWith("DAY_OF_WEEK")) { - printMacroName(targetMethodName); - print("((d, p) => d[\"UTC\"]?d.setUTCDay(p):d.setDay(p))("); - print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) - .print(")"); - return true; - } else if (first.endsWith("MONTH")) { - printMacroName(targetMethodName); - print("((d, p) => d[\"UTC\"]?d.setUTCMonth(p):d.setMonth(p))("); - print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) - .print(")"); - return true; - } else if (first.endsWith("HOUR_OF_DAY")) { - printMacroName(targetMethodName); - print("((d, p) => d[\"UTC\"]?d.setUTCHours(p):d.setHours(p))("); - print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) - .print(")"); - return true; - } else if (first.endsWith("MINUTE")) { - printMacroName(targetMethodName); - print("((d, p) => d[\"UTC\"]?d.setUTCMinutes(p):d.setMinutes(p))("); - print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) - .print(")"); - return true; - } else if (first.endsWith("MILLISECOND")) { - printMacroName(targetMethodName); - print("((d, p) => d[\"UTC\"]?d.setUTCMilliseconds(p):d.setMilliseconds(p))("); - print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) - .print(")"); - return true; - } else if (first.endsWith("SECOND")) { - printMacroName(targetMethodName); - print("((d, p) => d[\"UTC\"]?d.setUTCSeconds(p):d.setSeconds(p))("); - print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) - .print(")"); - return true; - } - } - break; - case "get": - if (invocation.getArgumentCount() == 1) { - String first = invocation.getArgument(0).toString(); - if (first.endsWith("YEAR")) { - printMacroName(targetMethodName); - print("(d => d[\"UTC\"]?d.getUTCFullYear():d.getFullYear())("); - print(invocation.getTargetExpression(), delegate).print(")"); - return true; - } else if (first.endsWith("DAY_OF_MONTH")) { - printMacroName(targetMethodName); - print("(d => d[\"UTC\"]?d.getUTCDate():d.getDate())("); - print(invocation.getTargetExpression(), delegate).print(")"); - return true; - } else if (first.endsWith("DAY_OF_WEEK")) { - printMacroName(targetMethodName); - print("(d => d[\"UTC\"]?d.getUTCDay():d.getDay())("); - print(invocation.getTargetExpression(), delegate).print(")"); - return true; - } else if (first.endsWith("MONTH")) { - printMacroName(targetMethodName); - print("(d => d[\"UTC\"]?d.getUTCMonth():d.getMonth())("); - print(invocation.getTargetExpression(), delegate).print(")"); - return true; - } else if (first.endsWith("HOUR_OF_DAY")) { - printMacroName(targetMethodName); - print("(d => d[\"UTC\"]?d.getUTCHours():d.getHours())("); - print(invocation.getTargetExpression(), delegate).print(")"); - return true; - } else if (first.endsWith("MINUTE")) { - printMacroName(targetMethodName); - print("(d => d[\"UTC\"]?d.getUTCMinutes():d.getMinutes())("); - print(invocation.getTargetExpression(), delegate).print(")"); - return true; - } else if (first.endsWith("MILLISECOND")) { - printMacroName(targetMethodName); - print("(d => d[\"UTC\"]?d.getUTCMilliseconds():d.getMilliseconds())("); - print(invocation.getTargetExpression(), delegate).print(")"); - return true; - } else if (first.endsWith("SECOND")) { - printMacroName(targetMethodName); - print("(d => d[\"UTC\"]?d.getUTCSeconds():d.getSeconds())("); - print(invocation.getTargetExpression(), delegate).print(")"); - return true; - } - } - break; - case "setTimeInMillis": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".setTime(").print(invocation.getArgument(0)) - .print(")"); - return true; - case "getTimeInMillis": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".getTime()"); - return true; - case "setTime": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".setTime(").print(invocation.getArgument(0)) - .print(".getTime())"); - return true; - case "getTime": - printMacroName(targetMethodName); - print("(new Date("); - print(invocation.getTargetExpression(), delegate).print(".getTime()))"); - return true; - } - return false; - } + protected boolean substituteMethodInvocationOnClass(MethodInvocationElement invocation, String targetMethodName, + boolean delegate) { - protected boolean substituteMethodInvocationOnMap(MethodInvocationElement invocation, String targetMethodName, - ExtendedElement targetExpression, boolean delegate) { - if (targetExpression == null) { - return false; - } + switch (targetMethodName) { + case "forName": + printMacroName(targetMethodName); + if (getContext().options.getModuleKind() != ModuleKind.none) { + print("eval(").print(invocation.getArgument(0)).print(".split('.').slice(-1)[0])"); + } else { + print("eval(").print(invocation.getArgument(0)).print(")"); + } + return true; + case "newInstance": + printMacroName(targetMethodName); + print("new ("); + print(invocation.getTargetExpression(), delegate).print(")(").printArgList(invocation.getArguments()) + .print(")"); + return true; + case "isInstance": + printMacroName(targetMethodName); + print("((c:any,o:any) => { if(typeof c === 'string') return (o.constructor && o.constructor") + .print("[\"" + Java2TypeScriptTranslator.INTERFACES_FIELD_NAME + "\"] && o.constructor") + .print("[\"" + Java2TypeScriptTranslator.INTERFACES_FIELD_NAME + "\"].indexOf(c) >= 0) || (o") + .print("[\"" + Java2TypeScriptTranslator.INTERFACES_FIELD_NAME + "\"] && o") + .print("[\"" + Java2TypeScriptTranslator.INTERFACES_FIELD_NAME + + "\"].indexOf(c) >= 0); else if(typeof c === 'function') return (o instanceof c) || (o.constructor && o.constructor === c); })("); + print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) + .print(")"); + return true; + case "isPrimitive": + // primitive class types are never used in JSweet, so it + // will always return false + printMacroName(targetMethodName); + print("(").print(invocation.getTargetExpression()).print(" === '__erasedPrimitiveType__'").print(")"); + return true; + case "getMethods": + case "getDeclaredMethods": + printMacroName(targetMethodName); + print("(c => Object.getOwnPropertyNames(c.prototype).filter(n => typeof c.prototype[n] == 'function').map(n => ({owner:c,name:n,fn:c.prototype[n]}) ) )(") + .print(invocation.getTargetExpression()).print(")"); + return true; + case "getMethod": + case "getDeclaredMethod": + printMacroName(targetMethodName); + print("((c,p) => { if(c.prototype.hasOwnProperty(p) && typeof c.prototype[p] == 'function') return {owner:c,name:p,fn:c.prototype[p]}; else return null; })(") + .print(invocation.getTargetExpression()).print(",").print(invocation.getArgument(0)).print(")"); + return true; + case "getField": + case "getDeclaredField": + printMacroName(targetMethodName); + print("((c,p) => { return {owner:c,name:p}; })(").print(invocation.getTargetExpression()).print(",") + .print(invocation.getArgument(0)).print(")"); + return true; + } + return false; + } - if (((DeclaredType) targetExpression.getType()).getTypeArguments().size() == 2 && types().isSameType( - ((DeclaredType) targetExpression.getType()).getTypeArguments().get(0), util().getType(String.class))) { - switch (targetMethodName) { - case "put": - printMacroName(targetMethodName); - print("("); - print(invocation.getTargetExpression(), delegate).print("[").print(invocation.getArgument(0)) - .print("] = ").print(invocation.getArgument(1)).print(")"); - return true; - case "get": - printMacroName(targetMethodName); - print("((m,k) => m[k]===undefined?null:m[k])("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") - .print(invocation.getArgument(0)).print(")"); - return true; - case "containsKey": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".hasOwnProperty(") - .print(invocation.getArgument(0)).print(")"); - return true; - case "keySet": - printMacroName(targetMethodName); - print("Object.keys("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "values": - printMacroName(targetMethodName); - print("(obj => Object.keys(obj).map(key => obj[key]))("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "size": - printMacroName(targetMethodName); - print("Object.keys("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(").length"); - return true; - case "isEmpty": - printMacroName(targetMethodName); - print("(Object.keys("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(").length == 0)"); - return true; - case "remove": - printMacroName(targetMethodName); - print("(map => { let deleted = "); - print(invocation.getTargetExpression(), delegate).print("[").print(invocation.getArgument(0)) - .print("];"); - print("delete "); - print(invocation.getTargetExpression(), delegate).print("[").print(invocation.getArgument(0)) - .print("];"); - print("return deleted;})").print("("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "clear": - printMacroName(targetMethodName); - print("(obj => { for (let member in obj) delete obj[member]; })("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "entrySet": - printMacroName(targetMethodName); - print("(o => { let s = []; for (let e in o) s.push({ k: e, v: o[e], getKey: function() { return this.k }, getValue: function() { return this.v } }); return s; })("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "clone": - printMacroName(targetMethodName); - print("(o => { let c = {}; for (let k in Object.keys(o)){ c[k] = o[k] } return c; })("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - } - } else { - String newEntry = "{key:k,value:v,getKey: function() { return this.key }, getValue: function() { return this.value }}"; - switch (targetMethodName) { - case "put": - case "setProperty": - printMacroName(targetMethodName); - print("((m,k,v) => { if(m.entries==null) m.entries=[]; for(let i=0;i"); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") - .printArgList(invocation.getArguments()).print(")"); - return true; - case "get": - case "getProperty": - printMacroName(targetMethodName); - print("((m,k) => { if(m.entries==null) m.entries=[]; for(let i=0;i"); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") - .printArgList(invocation.getArguments()).print(")"); - return true; - case "containsKey": - printMacroName(targetMethodName); - print("((m,k) => { if(m.entries==null) m.entries=[]; for(let i=0;i"); - print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) - .print(")"); - return true; - case "keySet": - case "stringPropertyNames": - printMacroName(targetMethodName); - print("((m) => { let r=[]; if(m.entries==null) m.entries=[]; for(let i=0;i"); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "values": - printMacroName(targetMethodName); - print("((m) => { let r=[]; if(m.entries==null) m.entries=[]; for(let i=0;i"); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "size": - printMacroName(targetMethodName); - print("((m) => { if(m.entries==null) m.entries=[]; return m.entries.length; })(").print(""); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "isEmpty": - printMacroName(targetMethodName); - print("((m) => { if(m.entries==null) m.entries=[]; return m.entries.length == 0; })(").print(""); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "remove": - printMacroName(targetMethodName); - print("((m,k) => { if(m.entries==null) m.entries=[]; for(let i=0;i"); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") - .printArgList(invocation.getArguments()).print(")"); - return true; - case "clear": - printMacroName(targetMethodName); - print("("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(").entries=[]"); - return true; - case "entrySet": - printMacroName(targetMethodName); - print("((m) => { if(m.entries==null) m.entries=[]; return m.entries; })(").print(""); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "clone": - printMacroName(targetMethodName); - print("(m => { if(m.entries==null) m.entries=[]; let c = {entries: []}; for(let i=0;i { for(let i=start;i { for(let i=0;i { if(a1==null && a2==null) return true; if(a1==null || a2==null) return false; if(a1.length != a2.length) return false; for(let i = 0; i < a1.length; i++) { if(a1[i] != a2[i]) return false; } return true; })(") + .printArgList(invocation.getArguments()).print(")"); + return true; + case "deepEquals": + printMacroName(targetMethodName); + print("(JSON.stringify(").print(invocation.getArgument(0)).print(") === JSON.stringify(") + .print(invocation.getArgument(1)).print("))"); + return true; + case "sort": + printMacroName(targetMethodName); + if (invocation.getArgumentCount() > 2) { + print("((arr, start, end, f?) => ((arr1, arr2) => arr1.splice.apply(arr1, ([start, arr2.length]).concat(arr2)))(") + .print(invocation.getArgument(0)).print(", ").print(invocation.getArgument(0)) + .print(".slice(start, end).sort(f)))(").printArgList(invocation.getArguments()).print(")"); + } else if (invocation.getArgumentCount() == 2) { + print("((l,c) => { if((c).compare) l.sort((e1,e2)=>(c).compare(e1,e2)); else l.sort(c); })(") + .print(invocation.getArgument(0)).print(",").print(invocation.getArgument(1)).print(")"); + } else { + print("((l) => {l.sort(); })(").print(invocation.getArgument(0)).print(")"); + } + return true; + } - } - } + return false; + } - return false; - } + protected boolean substituteMethodInvocationOnCollections(MethodInvocationElement invocation, + String targetMethodName, ExtendedElement targetExpression, boolean delegate) { + switch (targetMethodName) { + case "emptyList": + printMacroName(targetMethodName); + print("[]"); + return true; + case "emptySet": + printMacroName(targetMethodName); + print("[]"); + return true; + case "emptyMap": + printMacroName(targetMethodName); + print("{}"); + return true; + case "unmodifiableList": + case "unmodifiableCollection": + case "unmodifiableSet": + case "unmodifiableSortedSet": + printMacroName(targetMethodName); + printArgList(invocation.getArguments()).print(".slice(0)"); + return true; + case "singleton": + printMacroName(targetMethodName); + print("[").print(invocation.getArgument(0)).print("]"); + return true; + case "singletonList": + printMacroName(targetMethodName); + print("[").print(invocation.getArgument(0)).print("]"); + return true; + case "nCopies": + printMacroName(targetMethodName); + print("((n,v)=>{let c=[];for(let i=0;i { let o = {}; o[k] = ").print(invocation.getArgument(1)).print("; return o; })(") + .print(invocation.getArgument(0)).print(")"); + } + } else { + print("(k => { let o = {entries: [{getKey: function() { return this.key }, getValue: function() { return this.value },key:k, value:") + .print(invocation.getArgument(1)).print("}]}; return o; })(").print(invocation.getArgument(0)) + .print(")"); + } + return true; + case "binarySearch": + printMacroName(targetMethodName); + if (invocation.getArgumentCount() == 3) { + print("((l, key, c) => { let comp : any = c; if(typeof c != 'function') { comp = (a,b)=>c.compare(a,b); } let low = 0; let high = l.length-1; while (low <= high) { let mid = (low + high) >>> 1; let midVal = l[mid]; " + + "let cmp = comp(midVal, key); if (cmp < 0) low = mid + 1; else if (cmp > 0) high = mid - 1; else return mid; } " + + "return -(low + 1); })(").printArgList(invocation.getArguments()).print(")"); + return true; + } + if (invocation.getArgumentCount() == 2) { + if (util().isNumber(invocation.getArgument(1).getType())) { + print("((l, key) => { let comp = (a,b)=>a-b; let low = 0; let high = l.length-1; while (low <= high) { let mid = (low + high) >>> 1; let midVal = l[mid]; " + + "let cmp = comp(midVal, key); if (cmp < 0) low = mid + 1; else if (cmp > 0) high = mid - 1; else return mid; } " + + "return -(low + 1); })(").printArgList(invocation.getArguments()).print(")"); + return true; + } else { + print("((l, key) => { let comp = (a,b)=> {if(a.compareTo) return (a.compareTo(b)); else return a.localeCompare(b);}; let low = 0; let high = l.length-1; while (low <= high) { let mid = (low + high) >>> 1; let midVal = l[mid]; " + + "let cmp = comp(midVal, key); if (cmp < 0) low = mid + 1; else if (cmp > 0) high = mid - 1; else return mid; } " + + "return -(low + 1); })(").printArgList(invocation.getArguments()).print(")"); + return true; + } + } + case "sort": + printMacroName(targetMethodName); + if (invocation.getArgumentCount() == 2) { + print("((l,c) => { if((c).compare) l.sort((e1,e2)=>(c).compare(e1,e2)); else l.sort(c); })(") + .print(invocation.getArgument(0)).print(",").print(invocation.getArgument(1)).print(")"); + } else { + print(invocation.getArgument(0)).print(".sort(").printArgList(invocation.getArgumentTail()).print(")"); + } + return true; + case "reverse": + printMacroName(targetMethodName); + print(invocation.getArgument(0)).print(".reverse()"); + return true; + case "disjoint": + printMacroName(targetMethodName); + print("((c1, c2) => { for(let i=0;ic1[i])>=0) return false; } return true; } )(") + .printArgList(invocation.getArguments()).print(")"); + return true; + } - protected boolean substituteMethodInvocationOnArray(MethodInvocationElement invocation, String targetMethodName, - String targetClassName, boolean delegate) { - switch (targetMethodName) { - case "add": - case "addLast": - case "push": - case "addElement": - printMacroName(targetMethodName); - switch (targetClassName) { - case "java.util.Set": - case "java.util.HashSet": - case "java.util.TreeSet": - print("((s, e) => { if(s.indexOf(e)==-1) { s.push(e); return true; } else { return false; } })("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") - .print(invocation.getArgument(0)).print(")"); - break; - default: - if (invocation.getArgumentCount() == 2) { - print(invocation.getTargetExpression(), delegate).print(".splice(").print(invocation.getArgument(0)) - .print(", 0, ").print(invocation.getArgument(1)).print(")"); - } else { - print("("); - print(invocation.getTargetExpression(), delegate).print(".push(") - .printArgList(invocation.getArguments()).print(")>0)"); - } - } - return true; - case "addAll": - printMacroName(targetMethodName); - if (invocation.getArgumentCount() == 2) { - print("((l1, ndx, l2) => { for(let i=l2.length-1;i>=0;i--) l1.splice(ndx,0,l2[i]); })("); - print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) - .print(")"); - } else { - print("((l1, l2) => l1.push.apply(l1, l2))("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") - .printArgList(invocation.getArguments()).print(")"); - } - return true; - case "pop": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".pop(").printArgList(invocation.getArguments()) - .print(")"); - return true; - case "peek": - case "lastElement": - printMacroName(targetMethodName); - print("((s) => { return s[s.length-1]; })("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "remove": - case "removeFirst": // in Deque - case "removeElement": // in Vector: functionally equivalent to List.remove(int idx) - printMacroName(targetMethodName); - /* - * in Queue: interface contains a no-arg method remove() which is functionally - * identical to Deque.removeFirst() - */ - if (invocation.getArgumentCount() == 0) { - print(invocation.getTargetExpression(), delegate).print(".splice(0, 1)[0]"); - } else if (Util.isNumber(invocation.getArgument(0).getType()) - && types().isSubtype(types().erasure(invocation.getTargetExpression().getType()), - types().erasure(util().getType(List.class)))) { - print(invocation.getTargetExpression(), delegate).print(".splice(") - .printArgList(invocation.getArguments()).print(", 1)[0]"); - } else { - print("(a => { let index = a.indexOf(").print(invocation.getArgument(0)) - .print("); if(index>=0) { a.splice(index").print(invocation.getArgumentCount() == 1 ? "" : ", ") - .printArgList(invocation.getArgumentTail()) - .print(", 1); return true; } else { return false; }})("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - } - return true; - case "removeAll": - printMacroName(targetMethodName); - print("((a, r) => { let b=false; for(let i=0;i=0) { a.splice(ndx, 1); b=true; } } return b; })("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(",") - .print(invocation.getArgument(0)).print(")"); - return true; - case "containsAll": - printMacroName(targetMethodName); - print("((a, r) => { for(let i=0;ir[i])<0) return false; } return true; } )("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(",") - .print(invocation.getArgument(0)).print(")"); - return true; - case "retainAll": - printMacroName(targetMethodName); - print("((a, r) => { let b=false; for(let i=0;i a.length==0?null:a.shift())("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "pollLast": - printMacroName(targetMethodName); - print("(a => a.length==0?null:a.pop())("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - case "removeElementAt": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".splice(").printArgList(invocation.getArguments()) - .print(", 1)"); - return true; - case "subList": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print(".slice(").printArgList(invocation.getArguments()) - .print(")"); - return true; - case "size": - printMacroName(targetMethodName); - print("("); - print(invocation.getTargetExpression(), delegate).print(".length)"); - return true; - case "get": - case "elementAt": - printMacroName(targetMethodName); - print(invocation.getTargetExpression(), delegate).print("[").printArgList(invocation.getArguments()) - .print("]"); - return true; - case "set": - printMacroName(targetMethodName); - print("("); - print(invocation.getTargetExpression(), delegate).print("[").print(invocation.getArgument(0)).print("] = ") - .print(invocation.getArgument(1)).print(")"); - return true; - case "clear": - printMacroName(targetMethodName); - print("("); - print(invocation.getTargetExpression(), delegate).print(".length = 0)"); - return true; - case "isEmpty": - printMacroName(targetMethodName); - print("("); - print(invocation.getTargetExpression(), delegate).print(".length == 0)"); - return true; - case "contains": - printMacroName(targetMethodName); - print("("); - print(invocation.getTargetExpression(), delegate).print(".indexOf((").print(invocation.getArgument(0)) - .print(")) >= 0)"); - return true; - case "toArray": - printMacroName(targetMethodName); - if (invocation.getArgumentCount() == 1) { - ExtendedElement e = invocation.getArgument(0); - if (invocation.getTargetExpression() instanceof VariableAccessElement && e instanceof NewArrayElement) { - NewArrayElement newArray = (NewArrayElement) e; - boolean simplified = false; - if (newArray.getDimensionCount() == 1) { - ExtendedElement d = newArray.getDimension(0); - if (d.isConstant() && d.toString().equals("0")) { - simplified = true; - } else if (d instanceof MethodInvocationElement) { - if (((MethodInvocationElement) d).getMethodName().equals("size") - && ((MethodInvocationElement) d).getTargetExpression().toString() - .equals(invocation.getTargetExpression().toString())) { - simplified = true; - } - } - } - if (simplified) { - print(invocation.getTargetExpression(), delegate).print(".slice(0)"); - return true; - } - } - print("((a1, a2) => { if(a1.length >= a2.length) { a1.length=0; a1.push.apply(a1, a2); return a1; } else { return a2.slice(0); } })(") - .print(invocation.getArgument(0)).print(", "); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); - return true; - } else { - print(invocation.getTargetExpression(), delegate).print(".slice(0)"); - return true; - } - case "elements": - printMacroName(targetMethodName); - print("((a) => { var i = 0; return { nextElement: function() { return i { var i = 0; return { next: function() { return i { var i = 0; return { next: function() { return ival)) { result.push(parseInt(val,10)); } } return result; }()"); - return true; - case "equals": - printMacroName(targetMethodName); - print("((a1, a2) => { if(a1==null && a2==null) return true; if(a1==null || a2==null) return false; if(a1.length != a2.length) return false; for(let i = 0; i < a1.length; i++) { if(a1[i] != a2[i]) return false; } return true; })("); - printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") - .printArgList(invocation.getArguments()).print(")"); - return true; - } + return false; + } - return false; - } + private boolean substituteMethodInvocationOnStringBuilder(MethodInvocationElement invocation, + String targetMethodName, boolean delegate) { + switch (targetMethodName) { + case "append": + printMacroName(targetMethodName); + if (invocation.getArgumentCount() == 1) { + print("(sb => { sb.str += ").printArgList(invocation.getArguments()) + .print("; return sb; })("); + print(invocation.getTargetExpression(), delegate).print(")"); + } else { + print("(sb => { sb.str += (").print(invocation.getArgument(0)).print(").substr(") + .printArgList(invocation.getArgumentTail()).print("); return sb; })("); + print(invocation.getTargetExpression(), delegate).print(")"); + } + return true; + case "insert": + printMacroName(targetMethodName); + print("((sb, index, c) => { sb.str = sb.str.substr(0, index) + c + sb.str.substr(index); return sb; })("); + print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) + .print(")"); + return true; + case "setCharAt": + printMacroName(targetMethodName); + print("((sb, index, c) => sb.str = sb.str.substr(0, index) + c + sb.str.substr(index + 1))("); + print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) + .print(")"); + return true; + case "deleteCharAt": + printMacroName(targetMethodName); + print("((sb, index) => { sb.str = sb.str.substr(0, index) + sb.str.substr(index + 1); return sb; })("); + print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) + .print(")"); + return true; + case "delete": + printMacroName(targetMethodName); + print("((sb, i1, i2) => { sb.str = sb.str.substr(0, i1) + sb.str.substr(i2); return sb; })("); + print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) + .print(")"); + return true; + case "length": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".str.length"); + return true; + case "charAt": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".str.charAt(").print(invocation.getArgument(0)) + .print(")"); + return true; + case "setLength": + printMacroName(targetMethodName); + print("((sb, length) => sb.str = sb.str.substring(0, length))("); + print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) + .print(")"); + return true; + case "toString": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".str"); + return true; + case "lastIndexOf": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".str.lastIndexOf(") + .print(invocation.getArgument(0)).print(")"); + return true; + case "substring": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".str.substring(") + .printArgList(invocation.getArguments()).print(")"); + return true; + } + return false; + } - protected boolean substituteMethodInvocationOnNumber(MethodInvocationElement invocation, String targetMethodName) { - switch (targetMethodName) { - case "parseInt": - case "parseLong": - case "parseShort": - case "parseByte": - printMacroName(targetMethodName); - print("parseInt").print("(").printArgList(invocation.getArguments()).print(")"); - return true; - case "parseFloat": - case "parseDouble": - printMacroName(targetMethodName); - print("parseFloat").print("(").printArgList(invocation.getArguments()).print(")"); - return true; - case "floatToIntBits": - case "floatToRawIntBits": - printMacroName(targetMethodName); - print("((f) => { let buf = new ArrayBuffer(4); (new Float32Array(buf))[0]=f; return (new Uint32Array(buf))[0]; })(") - .printArgList(invocation.getArguments()).print(")"); - return true; - case "intBitsToFloat": - print("((v) => { let buf = new ArrayBuffer(4); (new Uint32Array(buf))[0]=v; return (new Float32Array(buf))[0]; })(") - .printArgList(invocation.getArguments()).print(")"); - return true; - case "doubleToLongBits": - case "doubleToRawLongBits": - printMacroName(targetMethodName); - print("((f) => { let buf = new ArrayBuffer(4); (new Float32Array(buf))[0]=f; return (new Uint32Array(buf))[0]; })((Math).fround(") - .printArgList(invocation.getArguments()).print("))"); - return true; - case "longBitsToDouble": - print("((v) => { let buf = new ArrayBuffer(4); (new Uint32Array(buf))[0]=v; return (new Float32Array(buf))[0]; })(") - .printArgList(invocation.getArguments()).print(")"); - return true; - case "valueOf": - if (util().isNumber(invocation.getArgument(0).getType())) { - print(invocation.getArgument(0)); - return true; - } else { - print("parseFloat").print("(").printArgList(invocation.getArguments()).print(")"); - return true; - } - } + protected boolean substituteMethodInvocationOnCalendar(MethodInvocationElement invocation, String targetMethodName, + boolean delegate) { + switch (targetMethodName) { + case "set": + if (invocation.getArgumentCount() == 2) { + String first = invocation.getArgument(0).toString(); + if (first.endsWith("YEAR")) { + printMacroName(targetMethodName); + print("((d, p) => d[\"UTC\"]?d.setUTCFullYear(p):d.setFullYear(p))("); + print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) + .print(")"); + return true; + } else if (first.endsWith("DAY_OF_MONTH")) { + printMacroName(targetMethodName); + print("((d, p) => d[\"UTC\"]?d.setUTCDate(p):d.setDate(p))("); + print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) + .print(")"); + return true; + } else if (first.endsWith("DAY_OF_WEEK")) { + printMacroName(targetMethodName); + print("((d, p) => d[\"UTC\"]?d.setUTCDay(p):d.setDay(p))("); + print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) + .print(")"); + return true; + } else if (first.endsWith("MONTH")) { + printMacroName(targetMethodName); + print("((d, p) => d[\"UTC\"]?d.setUTCMonth(p):d.setMonth(p))("); + print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) + .print(")"); + return true; + } else if (first.endsWith("HOUR_OF_DAY")) { + printMacroName(targetMethodName); + print("((d, p) => d[\"UTC\"]?d.setUTCHours(p):d.setHours(p))("); + print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) + .print(")"); + return true; + } else if (first.endsWith("MINUTE")) { + printMacroName(targetMethodName); + print("((d, p) => d[\"UTC\"]?d.setUTCMinutes(p):d.setMinutes(p))("); + print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) + .print(")"); + return true; + } else if (first.endsWith("MILLISECOND")) { + printMacroName(targetMethodName); + print("((d, p) => d[\"UTC\"]?d.setUTCMilliseconds(p):d.setMilliseconds(p))("); + print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) + .print(")"); + return true; + } else if (first.endsWith("SECOND")) { + printMacroName(targetMethodName); + print("((d, p) => d[\"UTC\"]?d.setUTCSeconds(p):d.setSeconds(p))("); + print(invocation.getTargetExpression(), delegate).print(", ").print(invocation.getArgument(1)) + .print(")"); + return true; + } + } + break; + case "get": + if (invocation.getArgumentCount() == 1) { + String first = invocation.getArgument(0).toString(); + if (first.endsWith("YEAR")) { + printMacroName(targetMethodName); + print("(d => d[\"UTC\"]?d.getUTCFullYear():d.getFullYear())("); + print(invocation.getTargetExpression(), delegate).print(")"); + return true; + } else if (first.endsWith("DAY_OF_MONTH")) { + printMacroName(targetMethodName); + print("(d => d[\"UTC\"]?d.getUTCDate():d.getDate())("); + print(invocation.getTargetExpression(), delegate).print(")"); + return true; + } else if (first.endsWith("DAY_OF_WEEK")) { + printMacroName(targetMethodName); + print("(d => d[\"UTC\"]?d.getUTCDay():d.getDay())("); + print(invocation.getTargetExpression(), delegate).print(")"); + return true; + } else if (first.endsWith("MONTH")) { + printMacroName(targetMethodName); + print("(d => d[\"UTC\"]?d.getUTCMonth():d.getMonth())("); + print(invocation.getTargetExpression(), delegate).print(")"); + return true; + } else if (first.endsWith("HOUR_OF_DAY")) { + printMacroName(targetMethodName); + print("(d => d[\"UTC\"]?d.getUTCHours():d.getHours())("); + print(invocation.getTargetExpression(), delegate).print(")"); + return true; + } else if (first.endsWith("MINUTE")) { + printMacroName(targetMethodName); + print("(d => d[\"UTC\"]?d.getUTCMinutes():d.getMinutes())("); + print(invocation.getTargetExpression(), delegate).print(")"); + return true; + } else if (first.endsWith("MILLISECOND")) { + printMacroName(targetMethodName); + print("(d => d[\"UTC\"]?d.getUTCMilliseconds():d.getMilliseconds())("); + print(invocation.getTargetExpression(), delegate).print(")"); + return true; + } else if (first.endsWith("SECOND")) { + printMacroName(targetMethodName); + print("(d => d[\"UTC\"]?d.getUTCSeconds():d.getSeconds())("); + print(invocation.getTargetExpression(), delegate).print(")"); + return true; + } + } + break; + case "setTimeInMillis": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".setTime(").print(invocation.getArgument(0)) + .print(")"); + return true; + case "getTimeInMillis": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".getTime()"); + return true; + case "setTime": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".setTime(").print(invocation.getArgument(0)) + .print(".getTime())"); + return true; + case "getTime": + printMacroName(targetMethodName); + print("(new Date("); + print(invocation.getTargetExpression(), delegate).print(".getTime()))"); + return true; + } + return false; + } - return false; - } + protected boolean substituteMethodInvocationOnMap(MethodInvocationElement invocation, String targetMethodName, + ExtendedElement targetExpression, boolean delegate) { + if (targetExpression == null) { + return false; + } - protected boolean substituteMethodInvocationOnCharacter(MethodInvocationElement invocation, - String targetMethodName) { - switch (targetMethodName) { - case "isDigit": - printMacroName(targetMethodName); - print("/\\d/.test(").printArgList(invocation.getArguments()).print("[0])"); - return true; - case "isLetter": - printMacroName(targetMethodName); - print("/[a-zA-Z]/.test(").printArgList(invocation.getArguments()).print("[0])"); - return true; - case "isAlphabetic": - printMacroName(targetMethodName); - print("/[a-zA-Z]/.test(").printArgList(invocation.getArguments()).print("[0])"); - return true; - case "isLetterOrDigit": - printMacroName(targetMethodName); - print("/[a-zA-Z\\d]/.test(").printArgList(invocation.getArguments()).print("[0])"); - return true; - case "toLowerCase": - printMacroName(targetMethodName); - print(invocation.getArgument(0)).print(".toLowerCase()"); - return true; - case "toUpperCase": - printMacroName(targetMethodName); - print(invocation.getArgument(0)).print(".toUpperCase()"); - return true; - case "isLowerCase": - printMacroName(targetMethodName); - print("(s => s.toLowerCase() === s)(").print(invocation.getArgument(0)).print(")"); - return true; - case "isUpperCase": - printMacroName(targetMethodName); - print("(s => s.toUpperCase() === s)(").print(invocation.getArgument(0)).print(")"); - return true; - case "charValue": - printMacroName(targetMethodName); - print(invocation.getTargetExpression()); - return true; - case "valueOf": - print(invocation.getArgument(0)); - return true; - case "toString": - if (invocation.getMethod().getModifiers().contains(Modifier.STATIC)) { - print(invocation.getArgument(0)); - return true; - } - } + if (((DeclaredType) targetExpression.getType()).getTypeArguments().size() == 2 && types().isSameType( + ((DeclaredType) targetExpression.getType()).getTypeArguments().get(0), util().getType(String.class))) { + switch (targetMethodName) { + case "put": + printMacroName(targetMethodName); + print("("); + print(invocation.getTargetExpression(), delegate).print("[").print(invocation.getArgument(0)) + .print("] = ").print(invocation.getArgument(1)).print(")"); + return true; + case "get": + printMacroName(targetMethodName); + print("((m,k) => m[k]===undefined?null:m[k])("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") + .print(invocation.getArgument(0)).print(")"); + return true; + case "containsKey": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".hasOwnProperty(") + .print(invocation.getArgument(0)).print(")"); + return true; + case "keySet": + printMacroName(targetMethodName); + print("Object.keys("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "values": + printMacroName(targetMethodName); + print("(obj => Object.keys(obj).map(key => obj[key]))("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "size": + printMacroName(targetMethodName); + print("Object.keys("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(").length"); + return true; + case "isEmpty": + printMacroName(targetMethodName); + print("(Object.keys("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(").length == 0)"); + return true; + case "remove": + printMacroName(targetMethodName); + print("(map => { let deleted = "); + print(invocation.getTargetExpression(), delegate).print("[").print(invocation.getArgument(0)) + .print("];"); + print("delete "); + print(invocation.getTargetExpression(), delegate).print("[").print(invocation.getArgument(0)) + .print("];"); + print("return deleted;})").print("("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "clear": + printMacroName(targetMethodName); + print("(obj => { for (let member in obj) delete obj[member]; })("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "entrySet": + printMacroName(targetMethodName); + print("(o => { let s = []; for (let e in o) s.push({ k: e, v: o[e], getKey: function() { return this.k }, getValue: function() { return this.v } }); return s; })("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "clone": + printMacroName(targetMethodName); + print("(o => { let c = {}; for (let k in Object.keys(o)){ c[k] = o[k] } return c; })("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + } + } else { + String newEntry = "{key:k,value:v,getKey: function() { return this.key }, getValue: function() { return this.value }}"; + switch (targetMethodName) { + case "put": + case "setProperty": + printMacroName(targetMethodName); + print("((m,k,v) => { if(m.entries==null) m.entries=[]; for(let i=0;i"); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") + .printArgList(invocation.getArguments()).print(")"); + return true; + case "get": + case "getProperty": + printMacroName(targetMethodName); + print("((m,k) => { if(m.entries==null) m.entries=[]; for(let i=0;i"); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") + .printArgList(invocation.getArguments()).print(")"); + return true; + case "containsKey": + printMacroName(targetMethodName); + print("((m,k) => { if(m.entries==null) m.entries=[]; for(let i=0;i"); + print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) + .print(")"); + return true; + case "keySet": + case "stringPropertyNames": + printMacroName(targetMethodName); + print("((m) => { let r=[]; if(m.entries==null) m.entries=[]; for(let i=0;i"); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "values": + printMacroName(targetMethodName); + print("((m) => { let r=[]; if(m.entries==null) m.entries=[]; for(let i=0;i"); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "size": + printMacroName(targetMethodName); + print("((m) => { if(m.entries==null) m.entries=[]; return m.entries.length; })(").print(""); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "isEmpty": + printMacroName(targetMethodName); + print("((m) => { if(m.entries==null) m.entries=[]; return m.entries.length == 0; })(").print(""); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "remove": + printMacroName(targetMethodName); + print("((m,k) => { if(m.entries==null) m.entries=[]; for(let i=0;i"); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") + .printArgList(invocation.getArguments()).print(")"); + return true; + case "clear": + printMacroName(targetMethodName); + print("("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(").entries=[]"); + return true; + case "entrySet": + printMacroName(targetMethodName); + print("((m) => { if(m.entries==null) m.entries=[]; return m.entries; })(").print(""); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "clone": + printMacroName(targetMethodName); + print("(m => { if(m.entries==null) m.entries=[]; let c = {entries: []}; for(let i=0;i { if(s.indexOf(e)==-1) { s.push(e); return true; } else { return false; } })("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") + .print(invocation.getArgument(0)).print(")"); + break; + default: + if (invocation.getArgumentCount() == 2) { + print(invocation.getTargetExpression(), delegate).print(".splice(").print(invocation.getArgument(0)) + .print(", 0, ").print(invocation.getArgument(1)).print(")"); + } else { + print("("); + print(invocation.getTargetExpression(), delegate).print(".push(") + .printArgList(invocation.getArguments()).print(")>0)"); + } + } + return true; + case "addAll": + printMacroName(targetMethodName); + if (invocation.getArgumentCount() == 2) { + print("((l1, ndx, l2) => { for(let i=l2.length-1;i>=0;i--) l1.splice(ndx,0,l2[i]); })("); + print(invocation.getTargetExpression(), delegate).print(", ").printArgList(invocation.getArguments()) + .print(")"); + } else { + print("((l1, l2) => l1.push.apply(l1, l2))("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") + .printArgList(invocation.getArguments()).print(")"); + } + return true; + case "pop": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".pop(").printArgList(invocation.getArguments()) + .print(")"); + return true; + case "peek": + case "lastElement": + printMacroName(targetMethodName); + print("((s) => { return s[s.length-1]; })("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "remove": + case "removeFirst": // in Deque + case "removeElement": // in Vector: functionally equivalent to List.remove(int idx) + printMacroName(targetMethodName); + /* + * in Queue: interface contains a no-arg method remove() which is functionally + * identical to Deque.removeFirst() + */ + if (invocation.getArgumentCount() == 0) { + print(invocation.getTargetExpression(), delegate).print(".splice(0, 1)[0]"); + } else if (Util.isNumber(invocation.getArgument(0).getType()) + && types().isSubtype(types().erasure(invocation.getTargetExpression().getType()), + types().erasure(util().getType(List.class)))) { + print(invocation.getTargetExpression(), delegate).print(".splice(") + .printArgList(invocation.getArguments()).print(", 1)[0]"); + } else { + print("(a => { let index = a.indexOf(").print(invocation.getArgument(0)) + .print("); if(index>=0) { a.splice(index").print(invocation.getArgumentCount() == 1 ? "" : ", ") + .printArgList(invocation.getArgumentTail()) + .print(", 1); return true; } else { return false; }})("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + } + return true; + case "removeAll": + printMacroName(targetMethodName); + print("((a, r) => { let b=false; for(let i=0;i=0) { a.splice(ndx, 1); b=true; } } return b; })("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(",") + .print(invocation.getArgument(0)).print(")"); + return true; + case "containsAll": + printMacroName(targetMethodName); + print("((a, r) => { for(let i=0;ir[i])<0) return false; } return true; } )("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(",") + .print(invocation.getArgument(0)).print(")"); + return true; + case "retainAll": + printMacroName(targetMethodName); + print("((a, r) => { let b=false; for(let i=0;i a.length==0?null:a.shift())("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "pollLast": + printMacroName(targetMethodName); + print("(a => a.length==0?null:a.pop())("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + case "removeElementAt": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".splice(").printArgList(invocation.getArguments()) + .print(", 1)"); + return true; + case "subList": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print(".slice(").printArgList(invocation.getArguments()) + .print(")"); + return true; + case "size": + printMacroName(targetMethodName); + print("("); + print(invocation.getTargetExpression(), delegate).print(".length)"); + return true; + case "get": + case "elementAt": + printMacroName(targetMethodName); + print(invocation.getTargetExpression(), delegate).print("[").printArgList(invocation.getArguments()) + .print("]"); + return true; + case "set": + printMacroName(targetMethodName); + print("("); + print(invocation.getTargetExpression(), delegate).print("[").print(invocation.getArgument(0)).print("] = ") + .print(invocation.getArgument(1)).print(")"); + return true; + case "clear": + printMacroName(targetMethodName); + print("("); + print(invocation.getTargetExpression(), delegate).print(".length = 0)"); + return true; + case "isEmpty": + printMacroName(targetMethodName); + print("("); + print(invocation.getTargetExpression(), delegate).print(".length == 0)"); + return true; + case "contains": + printMacroName(targetMethodName); + print("("); + print(invocation.getTargetExpression(), delegate).print(".indexOf((").print(invocation.getArgument(0)) + .print(")) >= 0)"); + return true; + case "toArray": + printMacroName(targetMethodName); + if (invocation.getArgumentCount() == 1) { + ExtendedElement e = invocation.getArgument(0); + if (invocation.getTargetExpression() instanceof VariableAccessElement && e instanceof NewArrayElement) { + NewArrayElement newArray = (NewArrayElement) e; + boolean simplified = false; + if (newArray.getDimensionCount() == 1) { + ExtendedElement d = newArray.getDimension(0); + if (d.isConstant() && d.toString().equals("0")) { + simplified = true; + } else if (d instanceof MethodInvocationElement) { + if (((MethodInvocationElement) d).getMethodName().equals("size") + && ((MethodInvocationElement) d).getTargetExpression().toString() + .equals(invocation.getTargetExpression().toString())) { + simplified = true; + } + } + } + if (simplified) { + print(invocation.getTargetExpression(), delegate).print(".slice(0)"); + return true; + } + } + print("((a1, a2) => { if(a1.length >= a2.length) { a1.length=0; a1.push.apply(a1, a2); return a1; } else { return a2.slice(0); } })(") + .print(invocation.getArgument(0)).print(", "); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(")"); + return true; + } else { + print(invocation.getTargetExpression(), delegate).print(".slice(0)"); + return true; + } + case "elements": + printMacroName(targetMethodName); + print("((a) => { var i = 0; return { nextElement: function() { return i { var i = 0; return { next: function() { return i { var i = 0; return { next: function() { return ival)) { result.push(parseInt(val,10)); } } return result; }()"); + return true; + case "equals": + printMacroName(targetMethodName); + print("((a1, a2) => { if(a1==null && a2==null) return true; if(a1==null || a2==null) return false; if(a1.length != a2.length) return false; for(let i = 0; i < a1.length; i++) { if(a1[i] != a2[i]) return false; } return true; })("); + printTargetForParameter(invocation.getTargetExpression(), delegate).print(", ") + .printArgList(invocation.getArguments()).print(")"); + return true; + } - try { - Field constantField = Class.forName(targetClassName).getDeclaredField(variableName); - print("" + constantField.get(null)); - } catch (Exception e) { - logger.warn("unable to read Java constant value " + targetClassName + "." + variableName, e); - print("Number." + variableName); - } - return true; - case "NaN": - print("NaN"); - return true; - } - break; - case "java.lang.Boolean": - switch (variableName) { - case "TRUE": - print("true"); - return true; - case "FALSE": - print("false"); - return true; - } - } + return false; + } - } - return super.substituteVariableAccess(variableAccess); - } + protected boolean substituteMethodInvocationOnNumber(MethodInvocationElement invocation, String targetMethodName) { + switch (targetMethodName) { + case "parseInt": + case "parseLong": + case "parseShort": + case "parseByte": + printMacroName(targetMethodName); + print("parseInt").print("(").printArgList(invocation.getArguments()).print(")"); + return true; + case "parseFloat": + case "parseDouble": + printMacroName(targetMethodName); + print("parseFloat").print("(").printArgList(invocation.getArguments()).print(")"); + return true; + case "floatToIntBits": + case "floatToRawIntBits": + printMacroName(targetMethodName); + print("((f) => { let buf = new ArrayBuffer(4); (new Float32Array(buf))[0]=f; return (new Uint32Array(buf))[0]; })(") + .printArgList(invocation.getArguments()).print(")"); + return true; + case "intBitsToFloat": + print("((v) => { let buf = new ArrayBuffer(4); (new Uint32Array(buf))[0]=v; return (new Float32Array(buf))[0]; })(") + .printArgList(invocation.getArguments()).print(")"); + return true; + case "doubleToLongBits": + case "doubleToRawLongBits": + printMacroName(targetMethodName); + print("((f) => { let buf = new ArrayBuffer(4); (new Float32Array(buf))[0]=f; return (new Uint32Array(buf))[0]; })((Math).fround(") + .printArgList(invocation.getArguments()).print("))"); + return true; + case "longBitsToDouble": + print("((v) => { let buf = new ArrayBuffer(4); (new Uint32Array(buf))[0]=v; return (new Float32Array(buf))[0]; })(") + .printArgList(invocation.getArguments()).print(")"); + return true; + case "valueOf": + if (util().isNumber(invocation.getArgument(0).getType())) { + print(invocation.getArgument(0)); + return true; + } else { + print("parseFloat").print("(").printArgList(invocation.getArguments()).print(")"); + return true; + } + } - @Override - public boolean substituteNewClass(NewClassElement newClass) { - String className = newClass.getTypeAsElement().toString(); + return false; + } - TypeMirror jdkSuperclass = context.getJdkSuperclass(className, excludedJavaSuperTypes); - boolean extendsJava = jdkSuperclass != null; - if (extendsJava) { - className = jdkSuperclass.toString(); - print("(() => { let __o : any = new ").print(newClass.getConstructorAccess()).print("(") - .printArgList(newClass.getArguments()).print("); __o.__delegate = "); - } - boolean substitute = false; + protected boolean substituteMethodInvocationOnCharacter(MethodInvocationElement invocation, + String targetMethodName) { + switch (targetMethodName) { + case "isDigit": + printMacroName(targetMethodName); + print("/\\d/.test(").printArgList(invocation.getArguments()).print("[0])"); + return true; + case "isLetter": + printMacroName(targetMethodName); + print("/[a-zA-Z]/.test(").printArgList(invocation.getArguments()).print("[0])"); + return true; + case "isAlphabetic": + printMacroName(targetMethodName); + print("/[a-zA-Z]/.test(").printArgList(invocation.getArguments()).print("[0])"); + return true; + case "isLetterOrDigit": + printMacroName(targetMethodName); + print("/[a-zA-Z\\d]/.test(").printArgList(invocation.getArguments()).print("[0])"); + return true; + case "toLowerCase": + printMacroName(targetMethodName); + print(invocation.getArgument(0)).print(".toLowerCase()"); + return true; + case "toUpperCase": + printMacroName(targetMethodName); + print(invocation.getArgument(0)).print(".toUpperCase()"); + return true; + case "isLowerCase": + printMacroName(targetMethodName); + print("(s => s.toLowerCase() === s)(").print(invocation.getArgument(0)).print(")"); + return true; + case "isUpperCase": + printMacroName(targetMethodName); + print("(s => s.toUpperCase() === s)(").print(invocation.getArgument(0)).print(")"); + return true; + case "charValue": + printMacroName(targetMethodName); + print(invocation.getTargetExpression()); + return true; + case "valueOf": + print(invocation.getArgument(0)); + return true; + case "toString": + if (invocation.getMethod().getModifiers().contains(Modifier.STATIC)) { + print(invocation.getArgument(0)); + return true; + } + } - switch (className) { - case "java.lang.Integer": - case "java.lang.Long": - case "java.lang.Double": - case "java.lang.Float": - case "java.long.Short": - case "java.util.Byte": - String argType = newClass.getArgument(0).getType().toString(); - boolean isCharArgument = Character.class.getName().equals(argType) || "char".equals(argType); - if (isCharArgument) { - print("new Number(").print(newClass.getArgument(0)).print(".charCodeAt(0)" + ").valueOf()"); - } else { - print("new Number(").print(newClass.getArgument(0)).print(").valueOf()"); - } - substitute = true; - break; - case "java.util.ArrayList": - case "java.util.LinkedList": - case "java.util.Vector": - case "java.util.Stack": - case "java.util.TreeSet": - case "java.util.HashSet": - case "java.util.AbstractSet": - case "java.util.AbstractCollection": - case "java.util.AbstractList": - case "java.util.AbstractQueue": - if (newClass.getArgumentCount() == 0) { - print("[]"); - } else { - if (Util.isNumber(newClass.getArgument(0).getType()) - || (newClass.getArgument(0) instanceof LiteralElement)) { - print("[]"); - } else { - print(newClass.getArgument(0)).print(".slice(0)"); - } - } - substitute = true; - break; - case "java.util.HashMap": - case "java.util.TreeMap": - case "java.util.Hashtable": - case "java.util.WeakHashMap": - case "java.util.LinkedHashMap": - if (newClass.getArgumentCount() == 0 || + return false; + } + + @Override + public boolean substituteVariableAccess(VariableAccessElement variableAccess) { + String targetClassName = variableAccess.getTargetElement().toString(); + String variableName = variableAccess.getVariableName(); + if (variableAccess.getVariable().getModifiers().contains(Modifier.STATIC) && isMappedType(targetClassName) + && targetClassName.startsWith("java.lang.") && !"class".equals(variableName)) { + + switch (targetClassName) { + case "java.lang.Float": + case "java.lang.Double": + case "java.lang.Integer": + case "java.lang.Byte": + case "java.lang.Long": + case "java.lang.Short": + switch (variableName) { + case "MIN_VALUE": + case "MAX_VALUE": + case "POSITIVE_INFINITY": + case "NEGATIVE_INFINITY": + + try { + Field constantField = Class.forName(targetClassName).getDeclaredField(variableName); + print("" + constantField.get(null)); + } catch (Exception e) { + logger.warn("unable to read Java constant value " + targetClassName + "." + variableName, e); + print("Number." + variableName); + } + return true; + case "NaN": + print("NaN"); + return true; + } + break; + case "java.lang.Boolean": + switch (variableName) { + case "TRUE": + print("true"); + return true; + case "FALSE": + print("false"); + return true; + } + } + + } + return super.substituteVariableAccess(variableAccess); + } + + @Override + public boolean substituteNewClass(NewClassElement newClass) { + String className = newClass.getTypeAsElement().toString(); + + TypeMirror jdkSuperclass = context.getJdkSuperclass(className, excludedJavaSuperTypes); + boolean extendsJava = jdkSuperclass != null; + if (extendsJava) { + className = jdkSuperclass.toString(); + print("(() => { let __o : any = new ").print(newClass.getConstructorAccess()).print("(") + .printArgList(newClass.getArguments()).print("); __o.__delegate = "); + } + boolean substitute = false; + + switch (className) { + case "java.lang.Integer": + case "java.lang.Long": + case "java.lang.Double": + case "java.lang.Float": + case "java.long.Short": + case "java.util.Byte": + String argType = newClass.getArgument(0).getType().toString(); + boolean isCharArgument = Character.class.getName().equals(argType) || "char".equals(argType); + if (isCharArgument) { + print("new Number(").print(newClass.getArgument(0)).print(".charCodeAt(0)" + ").valueOf()"); + } else { + print("new Number(").print(newClass.getArgument(0)).print(").valueOf()"); + } + substitute = true; + break; + case "java.util.ArrayList": + case "java.util.LinkedList": + case "java.util.Vector": + case "java.util.Stack": + case "java.util.TreeSet": + case "java.util.HashSet": + case "java.util.AbstractSet": + case "java.util.AbstractCollection": + case "java.util.AbstractList": + case "java.util.AbstractQueue": + if (newClass.getArgumentCount() == 0) { + print("[]"); + } else { + if (Util.isNumber(newClass.getArgument(0).getType()) + || (newClass.getArgument(0) instanceof LiteralElement)) { + print("[]"); + } else { + print(newClass.getArgument(0)).print(".slice(0)"); + } + } + substitute = true; + break; + case "java.util.HashMap": + case "java.util.TreeMap": + case "java.util.Hashtable": + case "java.util.WeakHashMap": + case "java.util.LinkedHashMap": + if (newClass.getArgumentCount() == 0 || !(newClass.getArgument(0).getType() instanceof Type.ClassType) || - !Util.isDeclarationOrSubClassDeclaration( - types(), (Type.ClassType) newClass.getArgument(0).getType(), Map.class.getName()) - ) { - print("{}"); - } else { - if (((DeclaredType) newClass.getType()).getTypeArguments().size() == 2 && types().isSameType( - ((DeclaredType) newClass.getType()).getTypeArguments().get(0), util().getType(String.class))) { - print("((o) => { let r = {}; for(let p in o) r[p]=o[p]; return r; })(") - .print(newClass.getArgument(0)).print(")"); - } else { - print("((o) => { let r = {}; r['entries'] = o.entries!=null?o.entries.slice():null; return r; })(") - .print(newClass.getArgument(0)).print(")"); - } - } - substitute = true; - break; - case "java.lang.String": - if (newClass.getArgumentCount() == 0) { - print("\"\""); - return true; - } else { - ExtendedElement firstArgument = newClass.getArgument(0); - if (firstArgument.getType() instanceof ArrayType) { - if (util().isIntegral(((ArrayType) firstArgument.getType()).getComponentType())) { - print("String.fromCharCode.apply(null, ").print(firstArgument).print(")"); - if (newClass.getArgumentCount() >= 3 && util().isIntegral(newClass.getArgument(1).getType()) - && util().isIntegral(newClass.getArgument(2).getType())) { - print(".substr(").print(newClass.getArgument(1)).print(", ").print(newClass.getArgument(2)) - .print(")"); - } - return true; - } else { - print(firstArgument).print(".join('')"); - if (newClass.getArgumentCount() >= 3 && util().isIntegral(newClass.getArgument(1).getType()) - && util().isIntegral(newClass.getArgument(2).getType())) { - print(".substr(").print(newClass.getArgument(1)).print(", ").print(newClass.getArgument(2)) - .print(")"); - } - return true; - } - } else if (StringBuffer.class.getName().equals(firstArgument.getTypeAsElement().toString()) - || StringBuilder.class.getName().equals(firstArgument.getTypeAsElement().toString())) { - print(firstArgument).print(".str"); - return true; - } - } - break; - case "java.lang.StringBuffer": - case "java.lang.StringBuilder": - if (newClass.getArgumentCount() == 0 || Util.isNumber(newClass.getArgument(0).getType())) { - print("{ str: \"\", toString: function() { return this.str; } }"); - } else { - print("{ str: ").print(newClass.getArgument(0)).print(", toString: function() { return this.str; } }"); - } - substitute = true; - break; - case "java.lang.ref.WeakReference": - print(newClass.getArgument(0)); - substitute = true; - break; - case "java.io.StringReader": - print("{ str: ").print(newClass.getArgument(0)).print(", cursor: 0 }"); - substitute = true; - break; - case "java.io.InputStreamReader": - case "java.io.BufferedReader": - print(newClass.getArgument(0)); - substitute = true; - break; - case "java.util.GregorianCalendar": - if (newClass.getArgumentCount() == 0) { - getPrinter().print("new Date()"); - substitute = true; - break; - } else if (newClass.getArgumentCount() == 1 - && TimeZone.class.getName().equals(newClass.getArgument(0).getType().toString())) { - if (newClass.getArgument(0) instanceof MethodInvocationElement) { - MethodInvocationElement inv = (MethodInvocationElement) newClass.getArgument(0); - if (inv.getMethodName().equals("getTimeZone") && inv.getArgument(0) instanceof LiteralElement - && ((LiteralElement) inv.getArgument(0)).getValue().equals("UTC")) { - getPrinter().print("(d => { d[\"UTC\"]=true; return d; })(new Date())"); - substitute = true; - break; - } - } - } - break; - } + !Util.isDeclarationOrSubClassDeclaration( + types(), (Type.ClassType) newClass.getArgument(0).getType(), Map.class.getName()) + ) { + print("{}"); + } else { + if (((DeclaredType) newClass.getType()).getTypeArguments().size() == 2 && types().isSameType( + ((DeclaredType) newClass.getType()).getTypeArguments().get(0), util().getType(String.class))) { + print("((o) => { let r = {}; for(let p in o) r[p]=o[p]; return r; })(") + .print(newClass.getArgument(0)).print(")"); + } else { + print("((o) => { let r = {}; r['entries'] = o.entries!=null?o.entries.slice():null; return r; })(") + .print(newClass.getArgument(0)).print(")"); + } + } + substitute = true; + break; + case "java.lang.String": + if (newClass.getArgumentCount() == 0) { + print("\"\""); + return true; + } else { + ExtendedElement firstArgument = newClass.getArgument(0); + if (firstArgument.getType() instanceof ArrayType) { + if (util().isIntegral(((ArrayType) firstArgument.getType()).getComponentType())) { + print("String.fromCharCode.apply(null, ").print(firstArgument).print(")"); + if (newClass.getArgumentCount() >= 3 && util().isIntegral(newClass.getArgument(1).getType()) + && util().isIntegral(newClass.getArgument(2).getType())) { + print(".substr(").print(newClass.getArgument(1)).print(", ").print(newClass.getArgument(2)) + .print(")"); + } + return true; + } else { + print(firstArgument).print(".join('')"); + if (newClass.getArgumentCount() >= 3 && util().isIntegral(newClass.getArgument(1).getType()) + && util().isIntegral(newClass.getArgument(2).getType())) { + print(".substr(").print(newClass.getArgument(1)).print(", ").print(newClass.getArgument(2)) + .print(")"); + } + return true; + } + } else if (StringBuffer.class.getName().equals(firstArgument.getTypeAsElement().toString()) + || StringBuilder.class.getName().equals(firstArgument.getTypeAsElement().toString())) { + print(firstArgument).print(".str"); + return true; + } + } + break; + case "java.lang.StringBuffer": + case "java.lang.StringBuilder": + if (newClass.getArgumentCount() == 0 || Util.isNumber(newClass.getArgument(0).getType())) { + print("{ str: \"\", toString: function() { return this.str; } }"); + } else { + print("{ str: ").print(newClass.getArgument(0)).print(", toString: function() { return this.str; } }"); + } + substitute = true; + break; + case "java.lang.ref.WeakReference": + print(newClass.getArgument(0)); + substitute = true; + break; + case "java.io.StringReader": + print("{ str: ").print(newClass.getArgument(0)).print(", cursor: 0 }"); + substitute = true; + break; + case "java.io.InputStreamReader": + case "java.io.BufferedReader": + print(newClass.getArgument(0)); + substitute = true; + break; + case "java.util.GregorianCalendar": + if (newClass.getArgumentCount() == 0) { + getPrinter().print("new Date()"); + substitute = true; + break; + } else if (newClass.getArgumentCount() == 1 + && TimeZone.class.getName().equals(newClass.getArgument(0).getType().toString())) { + if (newClass.getArgument(0) instanceof MethodInvocationElement) { + MethodInvocationElement inv = (MethodInvocationElement) newClass.getArgument(0); + if (inv.getMethodName().equals("getTimeZone") && inv.getArgument(0) instanceof LiteralElement + && ((LiteralElement) inv.getArgument(0)).getValue().equals("UTC")) { + getPrinter().print("(d => { d[\"UTC\"]=true; return d; })(new Date())"); + substitute = true; + break; + } + } + } + break; + } - if (!extendsJava && className.startsWith("java.")) { - if (types().isSubtype(newClass.getType(), context.symtab.throwableType)) { - print("Object.defineProperty("); - print("new Error("); - if (newClass.getArgumentCount() > 0) { - if (String.class.getName().equals(newClass.getArgument(0).getType().toString())) { - print(newClass.getArgument(0)); - } else if (types().isSubtype(newClass.getArgument(0).getType(), context.symtab.throwableType)) { - print(newClass.getArgument(0)).print(".message"); - } - } - print(")"); - Set classes = new HashSet<>(); - context.grabSuperClassNames(classes, newClass.getTypeAsElement()); - print(", '" + ERASED_CLASS_HIERARCHY_FIELD + "', { configurable: true, value: ["); - for (String c : classes) { - print("'" + c + "',"); - } - if (!classes.isEmpty()) { - removeLastChar(); - } - print("] })"); - return true; - } - } + if (!extendsJava && className.startsWith("java.")) { + if (types().isSubtype(newClass.getType(), context.symtab.throwableType)) { + print("Object.defineProperty("); + print("new Error("); + if (newClass.getArgumentCount() > 0) { + if (String.class.getName().equals(newClass.getArgument(0).getType().toString())) { + print(newClass.getArgument(0)); + } else if (types().isSubtype(newClass.getArgument(0).getType(), context.symtab.throwableType)) { + print(newClass.getArgument(0)).print(".message"); + } + } + print(")"); + Set classes = new HashSet<>(); + context.grabSuperClassNames(classes, newClass.getTypeAsElement()); + print(", '" + ERASED_CLASS_HIERARCHY_FIELD + "', { configurable: true, value: ["); + for (String c : classes) { + print("'" + c + "',"); + } + if (!classes.isEmpty()) { + removeLastChar(); + } + print("] })"); + return true; + } + } - if (!substitute) { - substitute = super.substituteNewClass(newClass); - } + if (!substitute) { + substitute = super.substituteNewClass(newClass); + } - if (extendsJava) { - print("; return __o; })()"); - } + if (extendsJava) { + print("; return __o; })()"); + } - return substitute; + return substitute; - } + } - @Override - public boolean substituteForEachLoop(ForeachLoopElement foreachLoop, boolean targetHasLength, String indexVarName) { - JCEnhancedForLoop loop = ((ForeachLoopElementSupport) foreachLoop).getTree(); - if (!targetHasLength && !isJDKPath(loop.expr.type.toString()) - && types().isSubtype(loop.expr.type, types().erasure(util().getType(Iterable.class)))) { - printForEachLoop(loop, indexVarName); - return true; - } - // return super.substituteForEachLoop(foreachLoop, targetHasLength, - // indexVarName); - return false; - } + @Override + public boolean substituteForEachLoop(ForeachLoopElement foreachLoop, boolean targetHasLength, String indexVarName) { + JCEnhancedForLoop loop = ((ForeachLoopElementSupport) foreachLoop).getTree(); + if (!targetHasLength && !isJDKPath(loop.expr.type.toString()) + && types().isSubtype(loop.expr.type, types().erasure(util().getType(Iterable.class)))) { + printForEachLoop(loop, indexVarName); + return true; + } + // return super.substituteForEachLoop(foreachLoop, targetHasLength, + // indexVarName); + return false; + } - @Override - public boolean eraseSuperClass(TypeElement classdecl, TypeElement superClass) { - return superClass.getQualifiedName().toString().startsWith("java.") - && !(superClass.asType().equals(context.symtab.throwableType) - || superClass.asType().equals(context.symtab.exceptionType) - || superClass.asType().equals(context.symtab.runtimeExceptionType) - || superClass.asType().equals(context.symtab.errorType)) - && !Util.isSourceElement(superClass); - } + @Override + public boolean eraseSuperClass(TypeElement classdecl, TypeElement superClass) { + return superClass.getQualifiedName().toString().startsWith("java.") + && !(superClass.asType().equals(context.symtab.throwableType) + || superClass.asType().equals(context.symtab.exceptionType) + || superClass.asType().equals(context.symtab.runtimeExceptionType) + || superClass.asType().equals(context.symtab.errorType)) + && !Util.isSourceElement(superClass); + } - @Override - public boolean eraseSuperInterface(TypeElement classdecl, TypeElement superInterface) { - return superInterface.getQualifiedName().toString().startsWith("java.") - && !Util.isSourceElement(superInterface); - } + @Override + public boolean eraseSuperInterface(TypeElement classdecl, TypeElement superInterface) { + return superInterface.getQualifiedName().toString().startsWith("java.") + && !Util.isSourceElement(superInterface); + } - @Override - public boolean isSubstituteSuperTypes() { - return true; - } + @Override + public boolean isSubstituteSuperTypes() { + return true; + } - @Override - public boolean substituteInstanceof(String exprStr, ExtendedElement expr, TypeMirror typeMirror) { - com.sun.tools.javac.code.Type type = (com.sun.tools.javac.code.Type) typeMirror; - String typeName = type.tsym.getQualifiedName().toString(); - if (typeName.startsWith("java.") && context.types.isSubtype(type, context.symtab.throwableType)) { - print(exprStr, expr); - print(" != null && "); - print("("); - print(exprStr, expr); - print("[\"" + ERASED_CLASS_HIERARCHY_FIELD + "\"] && "); - print(exprStr, expr); - print("[\"" + ERASED_CLASS_HIERARCHY_FIELD + "\"].indexOf(\"" + type.tsym.getQualifiedName().toString() - + "\") >= 0"); - print(")"); - if (context.getBaseThrowables().contains(typeName)) { - print(" || "); - return false; - } - return true; - } - String mappedType = extTypesMapping.get(typeName); - if ("string".equals(mappedType)) { - mappedType = "String"; - } - if ("boolean".equals(mappedType)) { - mappedType = "Boolean"; - } - if ("any".equals(mappedType) || (mappedType != null && mappedType.startsWith("{"))) { - mappedType = "Object"; - } - if (mappedType != null) { - if ("String".equals(mappedType)) { - print("typeof "); - print(exprStr, expr); - print(" === ").print("'string'"); - return true; - } else { - print(exprStr, expr); - print(" != null && "); - print("("); - print(exprStr, expr); - print(" instanceof " + mappedType); - print(")"); - return true; - } - } + @Override + public boolean substituteInstanceof(String exprStr, ExtendedElement expr, TypeMirror typeMirror) { + com.sun.tools.javac.code.Type type = (com.sun.tools.javac.code.Type) typeMirror; + String typeName = type.tsym.getQualifiedName().toString(); + if (typeName.startsWith("java.") && context.types.isSubtype(type, context.symtab.throwableType)) { + print(exprStr, expr); + print(" != null && "); + print("("); + print(exprStr, expr); + print("[\"" + ERASED_CLASS_HIERARCHY_FIELD + "\"] && "); + print(exprStr, expr); + print("[\"" + ERASED_CLASS_HIERARCHY_FIELD + "\"].indexOf(\"" + type.tsym.getQualifiedName().toString() + + "\") >= 0"); + print(")"); + if (context.getBaseThrowables().contains(typeName)) { + print(" || "); + return false; + } + return true; + } + String mappedType = extTypesMapping.get(typeName); + if ("string".equals(mappedType)) { + mappedType = "String"; + } + if ("boolean".equals(mappedType)) { + mappedType = "Boolean"; + } + if ("any".equals(mappedType) || (mappedType != null && mappedType.startsWith("{"))) { + mappedType = "Object"; + } + if (mappedType != null) { + if ("String".equals(mappedType)) { + print("typeof "); + print(exprStr, expr); + print(" === ").print("'string'"); + return true; + } else { + print(exprStr, expr); + print(" != null && "); + print("("); + print(exprStr, expr); + print(" instanceof " + mappedType); + print(")"); + return true; + } + } - return super.substituteInstanceof(exprStr, expr, type); - } + return super.substituteInstanceof(exprStr, expr, type); + } - @Override - public boolean substituteBinaryOperator(BinaryOperatorElement binaryOperator) { - if ("+".equals(binaryOperator.getOperator())) { - if (types().isSameType(util().getType(String.class), binaryOperator.getOperatorType().getReturnType())) { - if ("Array".equals( - extTypesMapping.get(types().erasure(binaryOperator.getLeftHandSide().getType()).toString()))) { - print("/* implicit toString */ (a => a?'['+a.join(', ')+']':'null')(") - .print(binaryOperator.getLeftHandSide()).print(") + ") - .print(binaryOperator.getRightHandSide()); - return true; - } else if ("Array".equals( - extTypesMapping.get(types().erasure(binaryOperator.getRightHandSide().getType()).toString()))) { - print(binaryOperator.getLeftHandSide()) - .print(" + /* implicit toString */ (a => a?'['+a.join(', ')+']':'null')(") - .print(binaryOperator.getRightHandSide()).print(")"); - return true; - } - } - } - return super.substituteBinaryOperator(binaryOperator); - } + @Override + public boolean substituteBinaryOperator(BinaryOperatorElement binaryOperator) { + if ("+".equals(binaryOperator.getOperator())) { + if (types().isSameType(util().getType(String.class), binaryOperator.getOperatorType().getReturnType())) { + if ("Array".equals( + extTypesMapping.get(types().erasure(binaryOperator.getLeftHandSide().getType()).toString()))) { + print("/* implicit toString */ (a => a?'['+a.join(', ')+']':'null')(") + .print(binaryOperator.getLeftHandSide()).print(") + ") + .print(binaryOperator.getRightHandSide()); + return true; + } else if ("Array".equals( + extTypesMapping.get(types().erasure(binaryOperator.getRightHandSide().getType()).toString()))) { + print(binaryOperator.getLeftHandSide()) + .print(" + /* implicit toString */ (a => a?'['+a.join(', ')+']':'null')(") + .print(binaryOperator.getRightHandSide()).print(")"); + return true; + } + } + } + return super.substituteBinaryOperator(binaryOperator); + } } diff --git a/transpiler/src/main/java/org/jsweet/transpiler/model/support/UtilSupport.java b/transpiler/src/main/java/org/jsweet/transpiler/model/support/UtilSupport.java index 99b9d7d4..887d8782 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/model/support/UtilSupport.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/model/support/UtilSupport.java @@ -125,6 +125,12 @@ public class UtilSupport implements Util { case "java.util.List": return context.symtab.listType; } + + TypeElement typeElement = context.elements().getTypeElement(clazz.getName()); + if (typeElement != null) { + return typeElement.asType(); + } + return null; } diff --git a/transpiler/src/test/java/.gitignore b/transpiler/src/test/java/.gitignore new file mode 100644 index 00000000..053143ae --- /dev/null +++ b/transpiler/src/test/java/.gitignore @@ -0,0 +1 @@ +/source/ diff --git a/transpiler/src/test/java/org/jsweet/test/transpiler/ApiTests.java b/transpiler/src/test/java/org/jsweet/test/transpiler/ApiTests.java index 9b05b3da..ce4c0696 100644 --- a/transpiler/src/test/java/org/jsweet/test/transpiler/ApiTests.java +++ b/transpiler/src/test/java/org/jsweet/test/transpiler/ApiTests.java @@ -40,6 +40,7 @@ import source.api.ForeachIteration; import source.api.J4TSInvocations; import source.api.JdkInvocations; import source.api.Numbers; +import source.api.Optionals; import source.api.PrimitiveInstantiation; import source.api.PromisesAsyncAwait; import source.api.QualifiedInstantiation; @@ -49,244 +50,246 @@ import source.api.WrongJdkInvocations; public class ApiTests extends AbstractTest { - // J4TS messes up with forbidden invocations... - @Ignore - @Test - public void testWrongJdkInvocations() { - transpile(logHandler -> { - // assertEquals(11, logHandler.reportedProblems.size()); - assertEquals(19, logHandler.reportedSourcePositions.get(0).getStartLine()); - assertEquals(39, logHandler.reportedSourcePositions.get(1).getStartLine()); - // assertEquals(41, - // logHandler.reportedSourcePositions.get(2).getStartLine()); - assertEquals(48, logHandler.reportedSourcePositions.get(3).getStartLine()); - assertEquals(52, logHandler.reportedSourcePositions.get(4).getStartLine()); - assertEquals(72, logHandler.reportedSourcePositions.get(5).getStartLine()); - // assertEquals(78, - // logHandler.reportedSourcePositions.get(6).getStartLine()); - // assertEquals(83, - // logHandler.reportedSourcePositions.get(7).getStartLine()); - assertEquals(87, logHandler.reportedSourcePositions.get(8).getStartLine()); - assertEquals(97, logHandler.reportedSourcePositions.get(9).getStartLine()); - assertEquals(118, logHandler.reportedSourcePositions.get(10).getStartLine()); - // assertEquals(120, - // logHandler.reportedSourcePositions.get(11).getStartLine()); - assertEquals(127, logHandler.reportedSourcePositions.get(12).getStartLine()); - assertEquals(131, logHandler.reportedSourcePositions.get(13).getStartLine()); - }, getSourceFile(J4TSInvocations.class), getSourceFile(WrongJdkInvocations.class)); - } + // J4TS messes up with forbidden invocations... + @Ignore + @Test + public void testWrongJdkInvocations() { + transpile(logHandler -> { + // assertEquals(11, logHandler.reportedProblems.size()); + assertEquals(19, logHandler.reportedSourcePositions.get(0).getStartLine()); + assertEquals(39, logHandler.reportedSourcePositions.get(1).getStartLine()); + // assertEquals(41, + // logHandler.reportedSourcePositions.get(2).getStartLine()); + assertEquals(48, logHandler.reportedSourcePositions.get(3).getStartLine()); + assertEquals(52, logHandler.reportedSourcePositions.get(4).getStartLine()); + assertEquals(72, logHandler.reportedSourcePositions.get(5).getStartLine()); + // assertEquals(78, + // logHandler.reportedSourcePositions.get(6).getStartLine()); + // assertEquals(83, + // logHandler.reportedSourcePositions.get(7).getStartLine()); + assertEquals(87, logHandler.reportedSourcePositions.get(8).getStartLine()); + assertEquals(97, logHandler.reportedSourcePositions.get(9).getStartLine()); + assertEquals(118, logHandler.reportedSourcePositions.get(10).getStartLine()); + // assertEquals(120, + // logHandler.reportedSourcePositions.get(11).getStartLine()); + assertEquals(127, logHandler.reportedSourcePositions.get(12).getStartLine()); + assertEquals(131, logHandler.reportedSourcePositions.get(13).getStartLine()); + }, getSourceFile(J4TSInvocations.class), getSourceFile(WrongJdkInvocations.class)); + } - @Test - public void testJ4TSInvocations() { - // with J4TS - transpilerTest().getTranspiler().setUsingJavaRuntime(true); - eval(ModuleKind.none, (logHandler, result) -> { - logHandler.assertNoProblems(); - }, getSourceFile(J4TSInvocations.class)); - // without J4TS + @Test + public void testJ4TSInvocations() { + // with J4TS + transpilerTest().getTranspiler().setUsingJavaRuntime(true); + eval(ModuleKind.none, (logHandler, result) -> { + logHandler.assertNoProblems(); + }, getSourceFile(J4TSInvocations.class)); + // without J4TS transpilerTest().getTranspiler().setUsingJavaRuntime(false); eval(ModuleKind.none, (logHandler, result) -> { logHandler.assertNoProblems(); }, getSourceFile(J4TSInvocations.class)); - } + } - @Test - public void testJdkInvocations() { - eval(ModuleKind.none, (logHandler, result) -> { - Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); - assertEquals("test", result.get("s1")); - assertEquals("m1", result.get("s2")); - assertEquals("e", result.get("s3")); - assertEquals("testc", result.get("s4")); - assertEquals(2, result.get("i1").intValue()); - assertEquals(-1, result.get("i2").intValue()); - assertEquals(4, result.get("l").intValue()); - assertEquals("t1st", result.get("r")); - }, getSourceFile(JdkInvocations.class)); - } + @Test + public void testJdkInvocations() { + eval(ModuleKind.none, (logHandler, result) -> { + Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); + assertEquals("test", result.get("s1")); + assertEquals("m1", result.get("s2")); + assertEquals("e", result.get("s3")); + assertEquals("testc", result.get("s4")); + assertEquals(2, result.get("i1").intValue()); + assertEquals(-1, result.get("i2").intValue()); + assertEquals(4, result.get("l").intValue()); + assertEquals("t1st", result.get("r")); + }, getSourceFile(JdkInvocations.class)); + } - @Test - public void testThreadLocal() { - eval((logHandler, result) -> { - Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); - assertEquals("coucou", result.get("out")); - assertEquals("nakach", result.get("out2")); - assertEquals("nakach", result.get("out3")); - }, getSourceFile(ThreadLocalFake.class)); - } + @Test + public void testThreadLocal() { + eval((logHandler, result) -> { + Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); + assertEquals("coucou", result.get("out")); + assertEquals("nakach", result.get("out2")); + assertEquals("nakach", result.get("out3")); + }, getSourceFile(ThreadLocalFake.class)); + } - @Test - public void testPromisesAsyncAwaits() { - eval((logHandler, result) -> { - Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); + @Test + public void testPromisesAsyncAwaits() { + eval((logHandler, result) -> { + Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); - // async await style - assertNotNull(result.get("t0")); - assertNotNull(result.get("t1")); - assertNotNull(result.get("t2")); + // async await style + assertNotNull(result.get("t0")); + assertNotNull(result.get("t1")); + assertNotNull(result.get("t2")); - long t0 = result.get("t0").longValue(); - long t1 = result.get("t1").longValue(); - long t2 = result.get("t2").longValue(); + long t0 = result.get("t0").longValue(); + long t1 = result.get("t1").longValue(); + long t2 = result.get("t2").longValue(); - assertTrue(t1 - t0 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS); - assertTrue(t2 - t1 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS); + assertTrue(t1 - t0 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS); + assertTrue(t2 - t1 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS); - assertEquals(new Integer(42), result.get("r1")); - assertEquals("my answer", result.get("r2")); - assertEquals("supermessage", result.get("e")); + assertEquals(new Integer(42), result.get("r1")); + assertEquals("my answer", result.get("r2")); + assertEquals("supermessage", result.get("e")); - // promise style - assertNotNull(result.get("2_t0")); - assertNotNull(result.get("2_t1")); - assertNotNull(result.get("2_t2")); + // promise style + assertNotNull(result.get("2_t0")); + assertNotNull(result.get("2_t1")); + assertNotNull(result.get("2_t2")); - t0 = result.get("2_t0").longValue(); - t1 = result.get("2_t1").longValue(); - t2 = result.get("2_t2").longValue(); + t0 = result.get("2_t0").longValue(); + t1 = result.get("2_t1").longValue(); + t2 = result.get("2_t2").longValue(); - assertTrue(t1 - t0 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS); - assertTrue(t2 - t1 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS); + assertTrue(t1 - t0 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS); + assertTrue(t2 - t1 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS); - assertEquals(new Integer(42), result.get("2_r1")); - assertEquals("my answer", result.get("2_r2")); - assertEquals("supermessage", result.get("2_e")); - - assertTrue(result.get("subMethod1")); - assertTrue(result.get("subMethod2")); - assertEquals("subMethod2", result.get("resultSubMethod2")); - - - }, getSourceFile(PromisesAsyncAwait.class)); - } + assertEquals(new Integer(42), result.get("2_r1")); + assertEquals("my answer", result.get("2_r2")); + assertEquals("supermessage", result.get("2_e")); - @Test - public void testForeachIteration() { - eval((logHandler, r) -> { - Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); - Assert.assertEquals("Wrong behavior output trace", "abc", r.get("out")); - }, getSourceFile(ForeachIteration.class)); - } + assertTrue(result.get("subMethod1")); + assertTrue(result.get("subMethod2")); + assertEquals("subMethod2", result.get("resultSubMethod2")); - @Test - public void testPrimitiveInstantiation() { - transpile(logHandler -> { - Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); - }, getSourceFile(PrimitiveInstantiation.class)); - } + }, getSourceFile(PromisesAsyncAwait.class)); + } - @Test - public void testAccessStaticMethod() { - transpile(logHandler -> { - Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); - }, getSourceFile(AccessStaticMethod.class)); - } + @Test + public void testForeachIteration() { + eval((logHandler, r) -> { + Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); + Assert.assertEquals("Wrong behavior output trace", "abc", r.get("out")); + }, getSourceFile(ForeachIteration.class)); + } - @Test - public void testQualifiedInstantiation() { - transpile(logHandler -> { - Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); - }, getSourceFile(QualifiedInstantiation.class)); - } + @Test + public void testPrimitiveInstantiation() { + transpile(logHandler -> { + Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); + }, getSourceFile(PrimitiveInstantiation.class)); + } - @Test - public void testCastMethods() { - transpile(logHandler -> { - Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); - }, getSourceFile(CastMethods.class)); - } + @Test + public void testAccessStaticMethod() { + transpile(logHandler -> { + Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); + }, getSourceFile(AccessStaticMethod.class)); + } - @Test - public void testErasingJava() { - transpile(logHandler -> { - logHandler.assertNoProblems(); - }, getSourceFile(ErasingJava.class)); - } + @Test + public void testQualifiedInstantiation() { + transpile(logHandler -> { + Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); + }, getSourceFile(QualifiedInstantiation.class)); + } - @Test - public void testStrings() { - eval(ModuleKind.none, (logHandler, r) -> { - logHandler.assertNoProblems(); - Assert.assertEquals( - "b,bc,c,bc,3,true,ab,32,b,0,false,true,source.api.Strings,Strings,abc,cdcdcd,true,false,true,false,true,true,false,a,aa", - r.get("trace")); - }, getSourceFile(Strings.class)); - } + @Test + public void testCastMethods() { + transpile(logHandler -> { + Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size()); + }, getSourceFile(CastMethods.class)); + } - @Test - public void testCharacters() { - eval(ModuleKind.none, (logHandler, r) -> { - logHandler.assertNoProblems(); + @Test + public void testErasingJava() { + transpile(logHandler -> { + logHandler.assertNoProblems(); + }, getSourceFile(ErasingJava.class)); + } - assertEquals(true, r.get("switch_int")); - assertEquals(true, r.get("switch_char")); - assertEquals(true, r.get("switch_char_cast_int")); - assertEquals(true, r.get("switch_char_cast_char")); - assertEquals(true, r.get("switch_int_cast_int")); - assertEquals(true, r.get("switch_int_cast_char")); + @Test + public void testStrings() { + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + Assert.assertEquals( + "b,bc,c,bc,3,true,ab,32,b,0,false,true,source.api.Strings,Strings,abc,cdcdcd,true,false,true,false,true,true,false,a,aa", + r.get("trace")); + }, getSourceFile(Strings.class)); + } - }, getSourceFile(Characters.class)); - } + @Test + public void testCharacters() { + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); - @Test - public void testNumbers() { - eval(ModuleKind.none, (logHandler, r) -> { - logHandler.assertNoProblems(); - }, getSourceFile(Numbers.class)); - } + assertEquals(true, r.get("switch_int")); + assertEquals(true, r.get("switch_char")); + assertEquals(true, r.get("switch_char_cast_int")); + assertEquals(true, r.get("switch_char_cast_char")); + assertEquals(true, r.get("switch_int_cast_int")); + assertEquals(true, r.get("switch_int_cast_char")); - @Test - public void testBooleans() { - eval(ModuleKind.none, (logHandler, r) -> { - logHandler.assertNoProblems(); - }, getSourceFile(Booleans.class)); - } + }, getSourceFile(Characters.class)); + } - @Test - public void testArrayBuffers() { - eval(ModuleKind.none, (logHandler, r) -> { - logHandler.assertNoProblems(); - Assert.assertEquals("0,0,1", r.get("trace")); - }, getSourceFile(ArrayBuffers.class)); - } + @Test + public void testNumbers() { + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + }, getSourceFile(Numbers.class)); + } - @Test - public void testExpressionBuilder() { - // evalWithJavaSupport((logHandler, r) -> { - // logHandler.assertNoProblems(); - // Assert.assertEquals(30, (int) r.get("result")); - // Assert.assertEquals(30, (int) r.get("result2")); - // }, getSourceFile(ExpressionBuilderTest.class), - // getSourceFile(ExpressionBuilderTest2.class)); - eval((logHandler, r) -> { - logHandler.assertNoProblems(); - Assert.assertEquals(30, (int) r.get("result")); - }, getSourceFile(ExpressionBuilderTest.class)); - eval((logHandler, r) -> { - logHandler.assertNoProblems(); - Assert.assertEquals(30, (int) r.get("result2")); - }, getSourceFile(ExpressionBuilderTest2.class)); - } - - @Test - public void testEquals() { - eval(ModuleKind.none, (logHandler, r) -> { - logHandler.assertNoProblems(); - Assert.assertEquals("false,true,false,true,false,true,false,false,true", r.get("trace")); - }, getSourceFile(Equals.class)); - } + @Test + public void testBooleans() { + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + }, getSourceFile(Booleans.class)); + } - @Test - public void testDates() { - eval(ModuleKind.none, (logHandler, r) -> { - logHandler.assertNoProblems(); + @Test + public void testArrayBuffers() { + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + Assert.assertEquals("0,0,1", r.get("trace")); + }, getSourceFile(ArrayBuffers.class)); + } + + @Test + public void testExpressionBuilder() { + // evalWithJavaSupport((logHandler, r) -> { + // logHandler.assertNoProblems(); + // Assert.assertEquals(30, (int) r.get("result")); + // Assert.assertEquals(30, (int) r.get("result2")); + // }, getSourceFile(ExpressionBuilderTest.class), + // getSourceFile(ExpressionBuilderTest2.class)); + eval((logHandler, r) -> { + logHandler.assertNoProblems(); + Assert.assertEquals(30, (int) r.get("result")); + }, getSourceFile(ExpressionBuilderTest.class)); + eval((logHandler, r) -> { + logHandler.assertNoProblems(); + Assert.assertEquals(30, (int) r.get("result2")); + }, getSourceFile(ExpressionBuilderTest2.class)); + } + + @Test + public void testEquals() { + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + Assert.assertEquals("false,true,false,true,false,true,false,false,true", r.get("trace")); + }, getSourceFile(Equals.class)); + } + + @Test + public void testDates() { + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); System.out.println("result = " + r.get("localeString")); - assertTrue(asList( - "1/1/2020, 1:00:00 AM", - "2020-1-1 1:00:00 AM").contains( - r.get("localeString"))); - - }, getSourceFile(Dates.class)); - } + assertTrue(asList("1/1/2020, 1:00:00 AM", "2020-1-1 1:00:00 AM").contains(r.get("localeString"))); + }, getSourceFile(Dates.class)); + } + + @Test + public void testOptional() { + eval((logHandler, result) -> { + logHandler.assertNoProblems(); + }, getSourceFile(Optionals.class)); + } } diff --git a/transpiler/src/test/java/source/api/Optionals.java b/transpiler/src/test/java/source/api/Optionals.java new file mode 100644 index 00000000..271730d6 --- /dev/null +++ b/transpiler/src/test/java/source/api/Optionals.java @@ -0,0 +1,103 @@ +package source.api; + +import java.util.Optional; + +import def.js.Error; + +public class Optionals { + private static final String PREFERRED_VALUE = "c'est la vie"; + + public static void main(String[] args) { + + } + + static void executePresentTests() { + Optional o = Optional.of(PREFERRED_VALUE); + assertContains(o, PREFERRED_VALUE); + + o = Optional.ofNullable(PREFERRED_VALUE); + assertContains(o, PREFERRED_VALUE); + + assert !o.equals(Optional.ofNullable(null)); + + assertContains(o.filter((current) -> current == PREFERRED_VALUE), PREFERRED_VALUE); + assertEmpty(o.filter((current) -> current == "XXXC'est la vie")); + + assertContains(o.flatMap(current -> Optional.of("new")), "new"); + assertContains(o.map(current -> "new2"), "new2"); + + String v = o.orElse("defaultVal"); + assert v == PREFERRED_VALUE; + v = o.orElseGet(() -> "defaultVal2"); + assert v == PREFERRED_VALUE; + + String[] modifiedForPresent = { "", "" }; + o.ifPresent(__ -> modifiedForPresent[0] = "modified"); + + assert modifiedForPresent[0] == "modified"; + assert modifiedForPresent[1] == "modified"; + + // TODO +// Object[] valsAfterStream = o.stream().toArray(); + } + + static void executeAbsentTests() { + Optional o = Optional.empty(); + assertEmpty(o); + + o = Optional.ofNullable(null); + assertEmpty(o); + + assert o.equals(Optional.ofNullable(null)); + + boolean caught = false; + try { + o = Optional.of(null); + } catch (Error e) { + caught = true; + } + assert caught; + + String v = o.orElse("defaultVal"); + assert v == "defaultVal"; + v = o.orElseGet(() -> "defaultVal2"); + assert v == "defaultVal2"; + + final String[] modified = { "", "" }; + o.ifPresent(__ -> modified[0] = "what"); + + assert modified[0] == ""; + assert modified[1] == "valid"; + } + + static void assertContains(Optional o, T value) { + assert o.get() == value; + assert o.isPresent(); + + o.orElseThrow(() -> new MyMissingError()); + } + + static void assertEmpty(Optional o) { + assert !o.isPresent(); + assert o != null; + + boolean caught = false; + try { + o.get(); + } catch (Error e) { + caught = true; + } + assert caught; + + caught = false; + try { + o.orElseThrow(() -> new MyMissingError()); + } catch (MyMissingError e) { + caught = true; + } + assert caught; + } +} + +class MyMissingError extends def.js.Error { +} \ No newline at end of file From 8ac9ef448c659d17b0034cc4591a512b53ac6947 Mon Sep 17 00:00:00 2001 From: Louis Grignon Date: Mon, 28 Sep 2020 15:57:31 +0200 Subject: [PATCH 2/3] fix #613 fix unresolved TypeMirror in util.getType(Class) => use available TypeElements --- .../src/main/java/org/jsweet/transpiler/JSweetContext.java | 3 +++ .../transpiler/extension/RemoveJavaDependenciesAdapter.java | 2 +- transpiler/src/main/java/org/jsweet/transpiler/model/Util.java | 1 - .../java/org/jsweet/transpiler/model/support/UtilSupport.java | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java b/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java index 2a361ec1..50c96a06 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java @@ -48,6 +48,7 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; @@ -68,6 +69,7 @@ import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; +import com.sun.tools.javac.model.JavacElements; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Types; @@ -1527,6 +1529,7 @@ public class JSweetContext extends Context { } } +<<<<<<< HEAD AnnotationMirror anno = getAnnotation(symbol, annotationType); T val = defaultValue; if (anno != null) { diff --git a/transpiler/src/main/java/org/jsweet/transpiler/extension/RemoveJavaDependenciesAdapter.java b/transpiler/src/main/java/org/jsweet/transpiler/extension/RemoveJavaDependenciesAdapter.java index 4e0069b7..0e207e1c 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/extension/RemoveJavaDependenciesAdapter.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/extension/RemoveJavaDependenciesAdapter.java @@ -69,7 +69,6 @@ import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; -import com.sun.tools.javac.code.Type; import org.jsweet.transpiler.JSweetContext; import org.jsweet.transpiler.Java2TypeScriptTranslator; import org.jsweet.transpiler.ModuleKind; @@ -86,6 +85,7 @@ import org.jsweet.transpiler.model.VariableAccessElement; import org.jsweet.transpiler.model.support.ForeachLoopElementSupport; import org.jsweet.transpiler.util.Util; +import com.sun.tools.javac.code.Type; import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop; import com.sun.tools.javac.tree.JCTree.JCLiteral; import com.sun.tools.javac.tree.JCTree.JCTypeApply; diff --git a/transpiler/src/main/java/org/jsweet/transpiler/model/Util.java b/transpiler/src/main/java/org/jsweet/transpiler/model/Util.java index 8cea6ecb..3aedce32 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/model/Util.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/model/Util.java @@ -33,7 +33,6 @@ public interface Util { * Gets the type from an existing runtime class when possible (return null * when the type cannot be found in the compiler's symbol table). *

- * This method only looks up well-known Java types. */ TypeMirror getType(Class clazz); diff --git a/transpiler/src/main/java/org/jsweet/transpiler/model/support/UtilSupport.java b/transpiler/src/main/java/org/jsweet/transpiler/model/support/UtilSupport.java index 887d8782..7d159e81 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/model/support/UtilSupport.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/model/support/UtilSupport.java @@ -130,7 +130,7 @@ public class UtilSupport implements Util { if (typeElement != null) { return typeElement.asType(); } - + return null; } From e3cfeed98e161ba050e8c8d80a14399654072c9f Mon Sep 17 00:00:00 2001 From: lgrignon Date: Fri, 27 Nov 2020 14:23:55 +0100 Subject: [PATCH 3/3] fix dumb compile error --- .../org/jsweet/transpiler/JSweetContext.java | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java b/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java index 50c96a06..0c902bf2 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java @@ -1529,7 +1529,6 @@ public class JSweetContext extends Context { } } -<<<<<<< HEAD AnnotationMirror anno = getAnnotation(symbol, annotationType); T val = defaultValue; if (anno != null) { @@ -1565,30 +1564,6 @@ public class JSweetContext extends Context { return defaultValue; } - // /** - // * Gets the value of the given annotation property. - // * - // * @param annotation - // * the annotation - // * @param propertyName - // * the name of the annotation property to get the value of - // * @param defaultValue - // * the value to return if not found - // */ - // @SuppressWarnings("unchecked") - // private static T getAnnotationValue(AnnotationMirror annotation, - // String propertyName, T defaultValue) { - // for (Map.Entry - // annoProperty : annotation - // .getElementValues().entrySet()) { - // if - // (annoProperty.getKey().getSimpleName().toString().equals(propertyName)) { - // return (T) annoProperty.getValue().getValue(); - // } - // } - // return defaultValue; - // } - /** * Gets the symbol's annotation that correspond to the given annotation type * name if exists. @@ -1602,19 +1577,6 @@ public class JSweetContext extends Context { return null; } - // /** - // * Gets the annotation tree that matches the given type name. - // */ - // private static JCAnnotation getAnnotation(List annotations, - // String annotationType) { - // for (JCAnnotation a : annotations) { - // if (annotationType.equals(a.type.toString())) { - // return a; - // } - // } - // return null; - // } - /** * Grabs the names of all the support interfaces in the class and interface * hierarchy.