overload fixes (+ tests + test with J4TS)

This commit is contained in:
Renaud Pawlak 2020-07-14 15:51:46 +02:00
parent 6c75ac877b
commit d2b2f69cd0
12 changed files with 31972 additions and 19 deletions

View File

@ -264,6 +264,12 @@
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jsweet</groupId>
<artifactId>j4ts</artifactId>
<version>0.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jsweet.candies</groupId>
<artifactId>jquery</artifactId>

View File

@ -720,11 +720,9 @@ public class JSweetTranspiler implements JSweetOptions {
SourceFile... sourceFiles) throws Exception {
logger.info("[" + engineName + " engine] eval files: " + Arrays.asList(sourceFiles));
EvalOptions options = new EvalOptions(isUsingModules(), workingDir);
if ("Java".equals(engineName)) {
JavaEval evaluator = new JavaEval(this, options);
JavaEval evaluator = new JavaEval(this, new EvalOptions(isUsingModules(), workingDir, false));
return evaluator.performEval(sourceFiles);
} else {
if (!areAllTranspiled(sourceFiles)) {
@ -755,7 +753,9 @@ public class JSweetTranspiler implements JSweetOptions {
jsFiles = Stream.of(sourceFiles).map(sourceFile -> sourceFile.getJsFile()).collect(toList());
}
JavaScriptEval evaluator = new JavaScriptEval(options, JavaScriptRuntime.NodeJs);
JavaScriptEval evaluator = new JavaScriptEval(
new EvalOptions(isUsingModules(), workingDir, context.isUsingJavaRuntime()),
JavaScriptRuntime.NodeJs);
return evaluator.performEval(jsFiles);
}
}

View File

@ -2642,7 +2642,9 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
}
print(getOverloadMethodName(method.sym)).print("(");
for (int j = 0; j < method.getParameters().size(); j++) {
if (j == method.getParameters().size() - 1 && Util.hasVarargs(overload.coreMethod.sym)) {
if (j == method.getParameters().size() - 1 && Util.hasVarargs(method.sym)) {
print("...");
} else if (j == method.getParameters().size() - 1 && Util.hasVarargs(overload.coreMethod.sym)) {
print("<any>");
}
print(avoidJSKeyword(overload.coreMethod.getParameters().get(j).name.toString())).print(", ");
@ -3154,9 +3156,17 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
int i = 0;
for (; i < m.getParameters().size(); i++) {
print("(");
if (Class.class.getName().equals(context.types.erasure(m.getParameters().get(i).type).toString())
&& m.getParameters().get(i).type.getTypeArguments().head != null
&& m.getParameters().get(i).type.getTypeArguments().head.isInterface()) {
print(avoidJSKeyword(overload.coreMethod.getParameters().get(i).name.toString())).print(" === ");
print(getStringLiteralQuote()).print(m.getParameters().get(i).type.getTypeArguments().head.toString())
.print(getStringLiteralQuote());
print(" || ");
}
printInstanceOf(avoidJSKeyword(overload.coreMethod.getParameters().get(i).name.toString()), null,
m.getParameters().get(i).type);
checkType(m.getParameters().get(i).type.tsym);
checkType(m.getParameters().get(i).type.tsym);
print(" || ")
.print(avoidJSKeyword(overload.coreMethod.getParameters().get(i).name.toString()) + " === null")
.print(")");
@ -3164,6 +3174,10 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
}
for (; i < overload.coreMethod.getParameters().size(); i++) {
print(avoidJSKeyword(overload.coreMethod.getParameters().get(i).name.toString())).print(" === undefined");
if (i == overload.coreMethod.getParameters().size() - 1 && overload.coreMethod.sym.isVarArgs()) {
print(" || ");
print(avoidJSKeyword(overload.coreMethod.getParameters().get(i).name.toString())).print(".length === 0");
}
print(" && ");
}
removeLastChars(4);
@ -4568,13 +4582,13 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
println().endIndent().printIndent().print("}");
if (!interfaces.isEmpty()) {
print(", '" + INTERFACES_FIELD_NAME + "', { configurable: true, value: ");
print(", 'constructor', { configurable: true, value: { " + INTERFACES_FIELD_NAME +": ");
print("[");
for (String i : interfaces) {
print(getStringLiteralQuote()).print(i).print(getStringLiteralQuote() + ",");
}
removeLastChar();
print("]");
print("] }");
print(" })");
}
} else {
@ -5856,7 +5870,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
if (context.isInterface(type.tsym)) {
print(" != null && ");
print("(");
print(exprStr, expr);
/*print(exprStr, expr);
if (checkFirstArrayElement)
print("[0]");
print("[" + getStringLiteralQuote() + INTERFACES_FIELD_NAME + getStringLiteralQuote() + "]")
@ -5864,9 +5878,10 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
print(exprStr, expr);
if (checkFirstArrayElement)
print("[0]");
print("[" + getStringLiteralQuote() + INTERFACES_FIELD_NAME + getStringLiteralQuote()
+ "].indexOf(\"").print(type.tsym.getQualifiedName().toString()).print("\") >= 0");
print(" || ");
print("[" + getStringLiteralQuote() + INTERFACES_FIELD_NAME
+ getStringLiteralQuote() + "].indexOf(\"")
.print(type.tsym.getQualifiedName().toString()).print("\") >= 0");
print(" || ");*/
print(exprStr, expr);
if (checkFirstArrayElement)
print("[0]");
@ -5889,6 +5904,20 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
print(" === " + getStringLiteralQuote() + "string" + getStringLiteralQuote());
}
print(")");
} else if (Class.class.getName().equals(type.tsym.getQualifiedName().toString())) {
print(" != null && ");
print("(");
print(exprStr, expr);
if (checkFirstArrayElement)
print("[0]");
print("[" + getStringLiteralQuote() + CLASS_NAME_IN_CONSTRUCTOR
+ getStringLiteralQuote() + "]").print(" != null");
print(" || ((t) => { try { new t; return true; } catch { return false; } })(");
print(exprStr, expr);
if (checkFirstArrayElement)
print("[0]");
print(")");
print(")");
} else {
if (type.tsym instanceof TypeVariableSymbol
|| Object.class.getName().equals(type.tsym.getQualifiedName().toString())) {
@ -5915,7 +5944,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
print(exprStr, expr);
if (checkFirstArrayElement)
print("[0]");
print(".length==0 || ");
print(".length == 0 || ");
print(exprStr, expr);
print("[0] == null ||");
if (t.elemtype instanceof ArrayType) {

View File

@ -5,10 +5,12 @@ import java.io.File;
public class EvalOptions {
public final boolean useModules;
public final File workingDir;
public final boolean useJavaRuntime;
public EvalOptions(boolean useModules, File workingDir) {
public EvalOptions(boolean useModules, File workingDir, boolean useJavaRuntime) {
this.useModules = useModules;
this.workingDir = workingDir;
this.useJavaRuntime = useJavaRuntime;
}
}

View File

@ -3,8 +3,10 @@ package org.jsweet.transpiler.eval;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.io.FileUtils;
@ -52,6 +54,12 @@ public class JavaScriptEval extends RuntimeEval {
File tmpFile = new File(options.workingDir, "eval.tmp_" + System.currentTimeMillis() + ".js");
FileUtils.deleteQuietly(tmpFile);
if (options.useJavaRuntime) {
List<File> newFiles = new ArrayList<>(jsFiles);
newFiles.add(0, new File("src/test/resources/j4ts.js"));
jsFiles = newFiles;
}
Set<File> alreadyWrittenScripts = new HashSet<>();
for (File jsFile : jsFiles) {
if (!alreadyWrittenScripts.contains(jsFile)) {
@ -61,7 +69,7 @@ public class JavaScriptEval extends RuntimeEval {
}
}
logger.info("[no modules] eval file: " + tmpFile + " jsFiles=" + jsFiles);
logger.info("[no modules] eval file: " + tmpFile + " jsFiles=" + jsFiles + ", useJavaRuntime=" + options.useJavaRuntime);
runProcess = runScript(trace, tmpFile);
}

View File

@ -1250,14 +1250,14 @@ public class Java2TypeScriptAdapter extends PrinterAdapter {
switch (targetMethodName) {
case "getName":
printMacroName(targetMethodName);
getPrinter().print("(c => c[\"" + Java2TypeScriptTranslator.CLASS_NAME_IN_CONSTRUCTOR + "\"]?c[\""
getPrinter().print("(c => typeof c === 'string'?c:c[\"" + Java2TypeScriptTranslator.CLASS_NAME_IN_CONSTRUCTOR + "\"]?c[\""
+ Java2TypeScriptTranslator.CLASS_NAME_IN_CONSTRUCTOR + "\"]:c[\"name\"])(");
printTarget(invocationElement.getTargetExpression());
print(")");
return true;
case "getSimpleName":
printMacroName(targetMethodName);
print("(c => c[\"" + Java2TypeScriptTranslator.CLASS_NAME_IN_CONSTRUCTOR + "\"]?c[\""
print("(c => typeof c === 'string'?(<any>c).substring((<any>c).lastIndexOf('.')+1):c[\"" + Java2TypeScriptTranslator.CLASS_NAME_IN_CONSTRUCTOR + "\"]?c[\""
+ Java2TypeScriptTranslator.CLASS_NAME_IN_CONSTRUCTOR + "\"].substring(c[\""
+ Java2TypeScriptTranslator.CLASS_NAME_IN_CONSTRUCTOR
+ "\"].lastIndexOf('.')+1):c[\"name\"].substring(c[\"name\"].lastIndexOf('.')+1))(");

View File

@ -78,14 +78,21 @@ public class ApiTests extends AbstractTest {
@Test
public void testJ4TSInvocations() {
transpile(ModuleKind.none, logHandler -> {
// 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((logHandler, result) -> {
eval(ModuleKind.none, (logHandler, result) -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
assertEquals("test", result.<String>get("s1"));
assertEquals("m1", result.<String>get("s2"));

View File

@ -62,6 +62,8 @@ import source.overload.ConstructorOverloadWithFieldInitializer;
import source.overload.InterfaceInheritance;
import source.overload.LocalVariablesNameCollision;
import source.overload.NonPublicRootMethod;
import source.overload.OverLoadClassAndObject;
import source.overload.OverLoadVarags;
import source.overload.OverLoadWithClassParam;
import source.overload.Overload;
import source.overload.OverloadInInnerClass;
@ -262,6 +264,31 @@ public class OverloadTests extends AbstractTest {
}, getSourceFile(ConstructorOverloadWithFieldInitializer.class));
}
@Test
public void testOverloadClassAndObjectWithJ4TS() {
transpilerTest().getTranspiler().setUsingJavaRuntime(true);
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
}, getSourceFile(OverLoadClassAndObject.class));
transpilerTest().getTranspiler().setUsingJavaRuntime(false);
}
@Test
public void testOverloadClassAndObject() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
}, getSourceFile(OverLoadClassAndObject.class));
}
@Test
public void testOverloadVarargs() {
transpilerTest().getTranspiler().setUsingJavaRuntime(true);
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
}, getSourceFile(OverLoadVarags.class));
transpilerTest().getTranspiler().setUsingJavaRuntime(false);
}
@Test
public void testConstructorOverloadWithArray() {
eval(ModuleKind.none, (logHandler, r) -> {

View File

@ -96,6 +96,7 @@ public class TranspilerTestRunner {
transpiler.setGenerateSourceMaps(false);
transpiler.setUseTsserver(true);
transpiler.setVerbose(verbose);
transpiler.setUsingJavaRuntime(false);
FileUtils.deleteQuietly(transpiler.getWorkingDirectory());
}

View File

@ -0,0 +1,62 @@
package source.overload;
import static jsweet.util.Lang.$apply;
import static jsweet.util.Lang.object;
public class OverLoadClassAndObject {
public static void main(String[] args) {
OverLoadClassAndObject overload = new OverLoadClassAndObject();
System.out.println(overload.m(AnInterface.class));
System.out.println(overload.m(new AClass()));
System.out.println((String)$apply(object(overload).$get("m"), new AClass()));
System.out.println((String)$apply(object(overload).$get("m"), AClass.class));
// Overload with strings cannot work because AnInterface.class is transpiled as a string
System.out.println((String)$apply(object(overload).$get("m"), AnInterface.class));
System.out.println(overload.m2(AClass.class));
System.out.println(overload.m2(new AClass()));
System.out.println((String)$apply(object(overload).$get("m2"), new AClass()));
System.out.println((String)$apply(object(overload).$get("m2"), AClass.class));
assert overload.m(AnInterface.class) == "2:source.overload.AnInterface";
assert overload.m(new AClass()) == "1:object";
assert $apply(object(overload).$get("m"), new AClass()) == "1:object";
assert $apply(object(overload).$get("m"), AClass.class) == "2:source.overload.AClass";
assert $apply(object(overload).$get("m"), AnInterface.class) == "2:source.overload.AnInterface";
assert overload.m2(AClass.class) == "2:source.overload.AClass";
assert overload.m2(new AClass()) == "1:object";
assert $apply(object(overload).$get("m2"), new AClass()) == "1:object";
assert $apply(object(overload).$get("m2"), AClass.class) == "2:source.overload.AClass";
}
String m(AnInterface o) {
return "1:" + o.getName();
}
String m(Class<AnInterface> clazz) {
return "2:" + clazz.getName();
}
String m2(AClass o) {
return "1:" + o.getName();
}
String m2(Class<AClass> clazz) {
return "2:" + clazz.getName();
}
}
interface AnInterface {
String getName();
}
class AClass implements AnInterface {
public String getName() {
return "object";
}
}

View File

@ -0,0 +1,50 @@
package source.overload;
import static jsweet.util.Lang.$insert;
public class OverLoadVarags {
public static void main(String[] args) {
OverLoadVarags ov = new OverLoadVarags();
System.out.println(ov.m(new AClass2()));
System.out.println(ov.m(new AClass2(), true, "a", "b", "c"));
System.out.println((String)$insert("ov.m(new AClass2())"));
System.out.println((String)$insert("ov.m(new AClass2(), true, 'a', 'b', 'c')"));
assert ov.m(new AClass2()) == "1:object";
assert ov.m(new AClass2(), true, "a", "b", "c") == "objecta,b,c/3";
assert $insert("ov.m(new AClass2())") == "1:object";
assert $insert("ov.m(new AClass2(), true, 'a', 'b', 'c')") == "objecta,b,c/3";
// passing an array does not work
// TODO: when invoking org method, test if passed expression type is an array and use call
//assert $insert("ov.m(new AClass2(), true, ['a', 'b', 'c'])") == "objecta,b,c/3";
assert ov.mref(new AClass2(), "a", "b", "c") == "objecta,b,c/3";
assert ov.mref(new AClass2(), new String[] {"a", "b", "c"}) == "objecta,b,c/3";
}
String m(AnInterface2 dto, boolean b, String... options) {
return dto.getName() + varM(options);
}
String m(AnInterface2 dto) {
return "1:" + dto.getName();
}
String mref(AnInterface2 dto, String... options) {
return dto.getName() + varM(options);
}
String varM(String... options) {
return "" + options + "/" + $insert("arguments.length");
}
}
interface AnInterface2 {
String getName();
}
class AClass2 implements AnInterface2 {
public String getName() {
return "object";
}
}

File diff suppressed because it is too large Load Diff