diff --git a/transpiler/src/main/java/org/jsweet/JSweetCommandLineLauncher.java b/transpiler/src/main/java/org/jsweet/JSweetCommandLineLauncher.java index 4165f798..e13b71e4 100644 --- a/transpiler/src/main/java/org/jsweet/JSweetCommandLineLauncher.java +++ b/transpiler/src/main/java/org/jsweet/JSweetCommandLineLauncher.java @@ -210,6 +210,14 @@ import com.martiansoftware.jsap.stringparsers.FileStringParser; to emulate the Java behavior. When disables, the code is more readable but it may result into runtime static initialization issues (cross-class static dependencies). + + [--disableOverloadStubs] + Do not generate overload stubs, but directly call the overloads instead. + Overload stubs are methods that implement a runtime switch on the parameter + types in order to automatically call the right overload. By default, overload + stubs are generated in order to ensure maximum interop, but they may + complicate the generated code and lead to runtime errors when the passed + argument types do not allow directing to the right overload at runtime. * * * @author Renaud Pawlak @@ -632,6 +640,18 @@ public class JSweetCommandLineLauncher { "Propagate automatically the async modifier when a method invokes an async method "+ "and automatically adds await keywords when invoking async methods."); jsap.registerParameter(switchArg); + + // Disable overload stubs + switchArg = new Switch(JSweetOptions.disableOverloadStubs); + switchArg.setLongFlag(JSweetOptions.disableOverloadStubs); + switchArg.setHelp( + "Do not generate overload stubs, but directly call the overloads instead." + + "Overload stubs are methods that implement a runtime switch on the parameter" + + "types in order to automatically call the right overload. By default, overload" + + "stubs are generated in order to ensure maximum interop, but they may" + + "complicate the generated code and lead to runtime errors when the passed" + + "argument types do not allow directing to the right overload at runtime."); + jsap.registerParameter(switchArg); return jsap; } @@ -871,6 +891,9 @@ public class JSweetCommandLineLauncher { if (jsapArgs.userSpecified(JSweetOptions.autoPropagateAsyncAwaits)) { transpiler.setAutoPropagateAsyncAwaits(jsapArgs.getBoolean(JSweetOptions.autoPropagateAsyncAwaits)); } + if (jsapArgs.userSpecified(JSweetOptions.disableOverloadStubs)) { + transpiler.setGenerateOverloadStubs(!jsapArgs.getBoolean(JSweetOptions.disableOverloadStubs)); + } if (tsOutputDir != null) { transpiler.setTsOutputDir(tsOutputDir); diff --git a/transpiler/src/main/java/org/jsweet/transpiler/JSweetOptions.java b/transpiler/src/main/java/org/jsweet/transpiler/JSweetOptions.java index af6ed41c..5a9e28ab 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/JSweetOptions.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/JSweetOptions.java @@ -148,6 +148,11 @@ public interface JSweetOptions { * Constant string for the 'autoPropagateAsyncs' option. */ String autoPropagateAsyncAwaits = "autoPropagateAsyncAwaits"; + + /** + * Constant string for the 'disableOverloadStubs' option. + */ + String disableOverloadStubs = "disableOverloadStubs"; /** * All the supported options (used to report non-blocking errors when options do not exist). @@ -156,7 +161,7 @@ public interface JSweetOptions { declaration, tsOnly, ignoreDefinitions, ignoreJavaErrors, header, disableSinglePrecisionFloats, disableStaticsLazyInitialization, targetVersion, tsout, dtsout, jsout, candiesJsOut, moduleResolution, extraSystemPath, useSingleQuotesForStringLiterals, nonEnumerableTransients, classpath, sortClassMembers, - autoPropagateAsyncAwaits }; + autoPropagateAsyncAwaits, disableOverloadStubs }; /** * Returns the configuration from the configuration file. @@ -387,4 +392,13 @@ public interface JSweetOptions { */ boolean isAutoPropagateAsyncAwaits(); + /** + * If true (default), generates overload stubs. Overload stubs are switch + * methods to invoke the overload with the original name. They perform runtime + * type check to invoke the right overload. + */ + boolean isGenerateOverloadStubs(); + + + } \ No newline at end of file diff --git a/transpiler/src/main/java/org/jsweet/transpiler/JSweetTranspiler.java b/transpiler/src/main/java/org/jsweet/transpiler/JSweetTranspiler.java index 60251844..c4ece9d9 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/JSweetTranspiler.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/JSweetTranspiler.java @@ -244,6 +244,7 @@ public class JSweetTranspiler implements JSweetOptions { private boolean nonEnumerableTransients = false; private boolean sortClassMembers = false; private boolean autoPropagateAsyncAwaits = false; + private boolean generateOverloadStubs = true; private ArrayList adapters = new ArrayList<>(); private File configurationFile; @@ -1978,4 +1979,15 @@ public class JSweetTranspiler implements JSweetOptions { this.autoPropagateAsyncAwaits = autoPropagateAsyncAwaits; } + @Override + public boolean isGenerateOverloadStubs() { + return this.generateOverloadStubs; + } + + public void setGenerateOverloadStubs(boolean generateOverloadStubs) { + this.generateOverloadStubs = generateOverloadStubs; + } + + + } diff --git a/transpiler/src/main/java/org/jsweet/transpiler/Java2TypeScriptTranslator.java b/transpiler/src/main/java/org/jsweet/transpiler/Java2TypeScriptTranslator.java index 56a0b407..bf2a2c26 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/Java2TypeScriptTranslator.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/Java2TypeScriptTranslator.java @@ -1842,17 +1842,19 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter { context.grabMethodsToBeImplemented(methods, t.tsym); } methods.sort((m1, m2) -> m1.getSimpleName().compareTo(m2.getSimpleName())); - Map signatures = new HashMap<>(); + Set signatures = new HashSet(); for (MethodSymbol meth : methods) { - if (meth.type instanceof MethodType && !context.hasAnnotationType(meth, JSweetConfig.ANNOTATION_ERASED) + Type methodType = context.types.erasureRecursive(meth.type); + + if (methodType instanceof MethodType && !context.hasAnnotationType(meth, JSweetConfig.ANNOTATION_ERASED) && !isMappedOrErasedType(meth.owner)) { // do not generate default abstract method for already // generated methods if (getScope().generatedMethodNames.contains(meth.name.toString())) { continue; } - MethodSymbol s = Util.findMethodDeclarationInType(getContext().types, classdecl.sym, - meth.getSimpleName().toString(), (MethodType) meth.type, true); + MethodSymbol s = Util.findMethodDeclarationInType2(getContext().types, classdecl.sym, + meth.getSimpleName().toString(), (MethodType) methodType); if (Object.class.getName().equals(s.getEnclosingElement().toString())) { s = null; } @@ -1865,20 +1867,22 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter { } } } - + + boolean invalidOverload = false; if (printAbstractDeclaration) { - Overload o = context.getOverload(classdecl.sym, meth); + Overload o = context.getOverload((TypeElement)s.getEnclosingElement(), s); if (o != null && o.methods.size() > 1 && !o.isValid) { - if (!meth.type.equals(o.coreMethod.type)) { + invalidOverload = true; + if (context.options.isGenerateOverloadStubs() && !meth.type.equals(o.coreMethod.type)) { printAbstractDeclaration = false; } } } if (s == null || printAbstractDeclaration) { - String signature = getContext().types.erasure(meth.type).toString(); - if (!(signatures.containsKey(meth.name) && signatures.get(meth.name).equals(signature))) { - printAbstractMethodDeclaration(meth); - signatures.put(meth.name, signature); + String signature = meth.name + " : " + methodType.toString(); + if (!(signatures.contains(signature))) { + printAbstractMethodDeclaration(meth, invalidOverload); + signatures.add(signature); } } } @@ -2156,18 +2160,32 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter { } - private void printAbstractMethodDeclaration(MethodSymbol method) { - printIndent().print("public abstract ").print(method.getSimpleName().toString()); - print("("); - if (method.getParameters() != null && !method.getParameters().isEmpty()) { - for (VarSymbol var : method.getParameters()) { - print(var.name.toString()).print("?: any"); - print(", "); + private void printAbstractMethodDeclaration(MethodSymbol method, boolean invalidOverload) { + if (context.options.isGenerateOverloadStubs() || !invalidOverload) { + printIndent().print("public abstract ").print(method.getSimpleName().toString()); + print("("); + if (method.getParameters() != null && !method.getParameters().isEmpty()) { + for (VarSymbol var : method.getParameters()) { + print(var.name.toString()).print("?: any"); + print(", "); + } + removeLastChars(2); } - removeLastChars(2); + print(")"); + print(": any;").println(); + } else { + printIndent().print("public abstract ").print(getOverloadMethodName(method)); + print("("); + if (method.getParameters() != null && !method.getParameters().isEmpty()) { + for (VarSymbol var : method.getParameters()) { + print(var.name.toString()).print("?: any"); + print(", "); + } + removeLastChars(2); + } + print(")"); + print(": any;").println(); } - print(")"); - print(": any;").println(); } private String getTSMethodName(JCMethodDecl methodDecl) { @@ -2273,13 +2291,22 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter { if (!overload.isValid) { if (!printCoreMethodDelegate) { if (overload.coreMethod.equals(methodDecl)) { - inCoreWrongOverload = true; - if (!isInterfaceMethod(parent, methodDecl) && !methodDecl.sym.isConstructor() - && parent.sym.equals(overload.coreMethod.sym.getEnclosingElement())) { - printCoreMethodDelegate = true; - visitMethodDef(overload.coreMethod); - println().println().printIndent(); - printCoreMethodDelegate = false; + if (context.options.isGenerateOverloadStubs()) { + inCoreWrongOverload = true; + if (!isInterfaceMethod(parent, methodDecl) && !methodDecl.sym.isConstructor() + && parent.sym.equals(overload.coreMethod.sym.getEnclosingElement())) { + printCoreMethodDelegate = true; + visitMethodDef(overload.coreMethod); + println().println().printIndent(); + printCoreMethodDelegate = false; + } + } else { + inCoreWrongOverload = true; + if (methodDecl.sym.isDefault() || (!methodDecl.sym.isConstructor() + && parent.sym.equals(overload.coreMethod.sym.getEnclosingElement()))) { + // print overload method with the right signature + inCoreWrongOverload = false; + } } } else { if (methodDecl.sym.isConstructor()) { @@ -2305,7 +2332,9 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter { } } if (isInterfaceMethod(parent, methodDecl)) { - return; + if (context.options.isGenerateOverloadStubs()) { + return; + } } } } @@ -2317,6 +2346,11 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter { } } + if (!context.options.isGenerateOverloadStubs() + && !methodDecl.sym.isConstructor() && inCoreWrongOverload && !printCoreMethodDelegate && !methodDecl.sym.isDefault()) { + return; + } + boolean ambient = context.hasAnnotationType(methodDecl.sym, JSweetConfig.ANNOTATION_AMBIENT); if (inOverload && !inCoreWrongOverload && (ambient || isDefinitionScope)) { @@ -4137,10 +4171,10 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter { } } if (methSym != null) { - if (context.isInvalidOverload(methSym) && !Util.hasTypeParameters(methSym) + if (context.isInvalidOverload(methSym) && ((!Util.hasTypeParameters(methSym) && !methSym.isDefault() && getParent(JCMethodDecl.class) != null - && !getParent(JCMethodDecl.class).sym.isDefault()) { - if (context.isInterface((TypeSymbol) methSym.getEnclosingElement())) { + && !getParent(JCMethodDecl.class).sym.isDefault()) || !context.options.isGenerateOverloadStubs())) { + if (context.options.isGenerateOverloadStubs() && context.isInterface((TypeSymbol) methSym.getEnclosingElement())) { removeLastChar('.'); print("['" + getOverloadMethodName(methSym) + "']"); } else { @@ -4905,7 +4939,6 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter { private String getFreeVariableName(String variablePrefix, int index) { String name = variablePrefix + (index == 0 ? "" : "" + index); - System.out.println("candidate name: " + name); Set generatedVariableNames = getGeneratedVariableNames(); diff --git a/transpiler/src/main/java/org/jsweet/transpiler/OverloadScanner.java b/transpiler/src/main/java/org/jsweet/transpiler/OverloadScanner.java index 80af68ec..e9884e25 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/OverloadScanner.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/OverloadScanner.java @@ -305,14 +305,14 @@ public class OverloadScanner extends AbstractTreeScanner { } /** - * Merges the given overload with a subclass one. + * Merges the given overload with another one. */ - public void merge(Types types, Overload subOverload) { + public void merge(Types types, Overload otherOverload) { // merge default methods for (JCMethodDecl m : methods) { if (m.getModifiers().getFlags().contains(Modifier.DEFAULT)) { boolean overriden = false; - for (JCMethodDecl subm : new ArrayList<>(subOverload.methods)) { + for (JCMethodDecl subm : new ArrayList<>(otherOverload.methods)) { if (subm.getParameters().size() == m.getParameters().size()) { overriden = true; for (int i = 0; i < subm.getParameters().size(); i++) { @@ -324,13 +324,13 @@ public class OverloadScanner extends AbstractTreeScanner { } } if (!overriden) { - safeAdd(types, subOverload, m); + safeAdd(types, otherOverload, m); } } } // merge other methods boolean merge = false; - for (JCMethodDecl subm : new ArrayList<>(subOverload.methods)) { + for (JCMethodDecl subm : new ArrayList<>(otherOverload.methods)) { boolean overrides = false; for (JCMethodDecl m : new ArrayList<>(methods)) { if (subm.getParameters().size() == m.getParameters().size()) { @@ -349,7 +349,7 @@ public class OverloadScanner extends AbstractTreeScanner { if (merge) { for (JCMethodDecl m : methods) { - safeAdd(types, subOverload, m); + safeAdd(types, otherOverload, m); } } } @@ -363,6 +363,7 @@ public class OverloadScanner extends AbstractTreeScanner { this.types = Types.instance(context); } + // only in pass 2 when all overloads have been created private void inspectSuperTypes(ClassSymbol clazz, Overload overload, JCMethodDecl method) { if (clazz == null) { return; @@ -370,6 +371,9 @@ public class OverloadScanner extends AbstractTreeScanner { Overload superOverload = context.getOverload(clazz, method.sym); if (superOverload != null && superOverload != overload) { superOverload.merge(types, overload); + if (!context.options.isGenerateOverloadStubs()) { + overload.merge(types, superOverload); + } } inspectSuperTypes((ClassSymbol) clazz.getSuperclass().tsym, overload, method); for (Type t : clazz.getInterfaces()) { @@ -431,10 +435,19 @@ public class OverloadScanner extends AbstractTreeScanner { for (JCCompilationUnit cu : cuList) { scan(cu); } + System.out.println("\nPASS 1"); + context.dumpOverloads(System.out); pass++; for (JCCompilationUnit cu : cuList) { scan(cu); } + if (!context.options.isGenerateOverloadStubs()) { + for (JCCompilationUnit cu : cuList) { + scan(cu); + } + } + System.out.println("\nPASS 2"); + context.dumpOverloads(System.out); for (Overload overload : context.getAllOverloads()) { overload.calculate(types, context.symtab); if (overload.methods.size() > 1 && !overload.isValid) { @@ -443,7 +456,8 @@ public class OverloadScanner extends AbstractTreeScanner { } } } - // context.dumpOverloads(System.out); + System.out.println("\nPASS 3"); + context.dumpOverloads(System.out); } } diff --git a/transpiler/src/main/java/org/jsweet/transpiler/util/Util.java b/transpiler/src/main/java/org/jsweet/transpiler/util/Util.java index d9de6c41..eb2eb0ff 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/util/Util.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/util/Util.java @@ -426,14 +426,13 @@ public class Util { // score them for (MethodSymbol candidate : candidates) { - if(types.isSubSignature(candidate.type, methodType)) { + if(types.isSubSignature(types.erasureRecursive(candidate.type), types.erasureRecursive(methodType))) { return candidate; } } return null; } - - + /** * Finds the method in the given type that matches the given name and * signature. diff --git a/transpiler/src/test/java/org/jsweet/test/transpiler/OverloadTests.java b/transpiler/src/test/java/org/jsweet/test/transpiler/OverloadTests.java index 807a29cc..3bcbddd1 100644 --- a/transpiler/src/test/java/org/jsweet/test/transpiler/OverloadTests.java +++ b/transpiler/src/test/java/org/jsweet/test/transpiler/OverloadTests.java @@ -63,7 +63,9 @@ import source.overload.InterfaceInheritance; import source.overload.LocalVariablesNameCollision; import source.overload.NonPublicRootMethod; import source.overload.OverLoadClassAndObject; +import source.overload.OverLoadClassAndObjectNoStubs; import source.overload.OverLoadVarags; +import source.overload.OverLoadVaragsNoStubs; import source.overload.OverLoadWithClassParam; import source.overload.Overload; import source.overload.OverloadInInnerClass; @@ -107,6 +109,14 @@ public class OverloadTests extends AbstractTest { assertEquals("s11", result.get("res2")); assertEquals("s22", result.get("res3")); }, getSourceFile(Overload.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, result) -> { + logHandler.assertNoProblems(); + assertEquals("default1", result.get("res1")); + assertEquals("s11", result.get("res2")); + assertEquals("s22", result.get("res3")); + }, getSourceFile(Overload.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -114,6 +124,11 @@ public class OverloadTests extends AbstractTest { eval((logHandler, result) -> { logHandler.assertNoProblems(); }, getSourceFile(OverloadWithSuperclass.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, result) -> { + logHandler.assertNoProblems(); + }, getSourceFile(OverloadWithSuperclass.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -122,6 +137,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertEquals("1,2,3,4,5,6,7", r.get("trace")); }, getSourceFile(WrongOverload.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("1,2,3,4,5,6,7", r.get("trace")); + }, getSourceFile(WrongOverload.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -130,6 +151,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertEquals("1,5,2,3,2,4,test5,tutu,2,4,1,tutu,6", r.get("trace")); }, getSourceFile(WrongOverloads.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("1,5,2,3,2,4,test5,tutu,2,4,1,tutu,6", r.get("trace")); + }, getSourceFile(WrongOverloads.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -138,6 +165,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertEquals("draw0,draw1", r.get("trace")); }, getSourceFile(WrongOverloadsWithDefaultMethods.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("draw0,draw1", r.get("trace")); + }, getSourceFile(WrongOverloadsWithDefaultMethods.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -146,6 +179,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertEquals("draw0,draw1,double1,float1", r.get("trace")); }, getSourceFile(WrongOverloadsWithNonCoreMethod.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("draw0,draw1,double1,float1", r.get("trace")); + }, getSourceFile(WrongOverloadsWithNonCoreMethod.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -153,6 +192,11 @@ public class OverloadTests extends AbstractTest { transpile(ModuleKind.none, (logHandler) -> { logHandler.assertNoProblems(); }, getSourceFile(OverloadInInnerClass.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + transpile(ModuleKind.none, (logHandler) -> { + logHandler.assertNoProblems(); + }, getSourceFile(OverloadInInnerClass.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -160,6 +204,11 @@ public class OverloadTests extends AbstractTest { transpile(ModuleKind.none, (logHandler) -> { logHandler.assertNoProblems(); }, getSourceFile(WrongOverloadInInnerClass.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + transpile(ModuleKind.none, (logHandler) -> { + logHandler.assertNoProblems(); + }, getSourceFile(WrongOverloadInInnerClass.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -167,6 +216,11 @@ public class OverloadTests extends AbstractTest { eval((logHandler, r) -> { logHandler.assertNoProblems(); }, getSourceFile(WrongOverloadWithArraysAndObjects.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, r) -> { + logHandler.assertNoProblems(); + }, getSourceFile(WrongOverloadWithArraysAndObjects.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -175,6 +229,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertEquals("1,2,3,4", r.get("trace")); }, getSourceFile(WrongOverloadWithGenerics.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("1,2,3,4", r.get("trace")); + }, getSourceFile(WrongOverloadWithGenerics.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -183,6 +243,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertEquals("0-88,0-99,1-s1,m2,2-99-s2,3-true,m1,4,5-5,5-6,m3,6,7,test2,test1", r.get("trace")); }, getSourceFile(WrongOverloadWithInheritance.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("0-88,0-99,1-s1,m2,2-99-s2,3-true,m1,4,5-5,5-6,m3,6,7,test2,test1", r.get("trace")); + }, getSourceFile(WrongOverloadWithInheritance.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -192,6 +258,13 @@ public class OverloadTests extends AbstractTest { assertEquals(true, r.get("static")); assertEquals(true, r.get("instance")); }, getSourceFile(OverloadWithStaticAndInstanceMethods.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals(true, r.get("static")); + assertEquals(true, r.get("instance")); + }, getSourceFile(OverloadWithStaticAndInstanceMethods.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -200,6 +273,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertEquals("remove1: abc,remove2: 1", r.get("trace")); }, getSourceFile(WrongOverloadFrom2Interfaces.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("remove1: abc,remove2: 1", r.get("trace")); + }, getSourceFile(WrongOverloadFrom2Interfaces.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -207,6 +286,11 @@ public class OverloadTests extends AbstractTest { transpile(ModuleKind.none, (logHandler) -> { logHandler.assertNoProblems(); }, getSourceFile(InterfaceInheritance.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + transpile(ModuleKind.none, (logHandler) -> { + logHandler.assertNoProblems(); + }, getSourceFile(InterfaceInheritance.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -214,6 +298,11 @@ public class OverloadTests extends AbstractTest { transpile(ModuleKind.none, (logHandler) -> { logHandler.assertNoProblems(); }, getSourceFile(NonPublicRootMethod.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + transpile(ModuleKind.none, (logHandler) -> { + logHandler.assertNoProblems(); + }, getSourceFile(NonPublicRootMethod.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -223,6 +312,13 @@ public class OverloadTests extends AbstractTest { assertEquals("1-1-X,1-1-0,1-2-X,1-2-0,1-3-X,1-3-0,2-1-X,2-1-0,2-2-X,2-2-0,2-3-X,2-3-0,0-3-X", r.get("trace")); }, getSourceFile(BasicOverride.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("1-1-X,1-1-0,1-2-X,1-2-0,1-3-X,1-3-0,2-1-X,2-1-0,2-2-X,2-2-0,2-3-X,2-3-0,0-3-X", + r.get("trace")); + }, getSourceFile(BasicOverride.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -230,6 +326,11 @@ public class OverloadTests extends AbstractTest { eval(ModuleKind.none, (logHandler, r) -> { logHandler.assertNoProblems(); }, getSourceFile(OverloadWithAbstractClass.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + }, getSourceFile(OverloadWithAbstractClass.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -238,6 +339,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertEquals("m,m,m,read1,read2", r.get("trace")); }, getSourceFile(WrongOverloadWithSpecialParameters.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("m,m,m,read1,read2", r.get("trace")); + }, getSourceFile(WrongOverloadWithSpecialParameters.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -246,6 +353,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertEquals("c11,t12,c13,t14", r.get("trace")); }, getSourceFile(WrongOverloadConstructorWithVarargs.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("c11,t12,c13,t14", r.get("trace")); + }, getSourceFile(WrongOverloadConstructorWithVarargs.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -254,6 +367,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertEquals("1,2,3,4,5,6,7", r.get("trace")); }, getSourceFile(WrongOverloadConstructorWithParamNameCollision.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("1,2,3,4,5,6,7", r.get("trace")); + }, getSourceFile(WrongOverloadConstructorWithParamNameCollision.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -262,6 +381,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertEquals("test,1", r.get("trace")); }, getSourceFile(ConstructorOverloadWithFieldInitializer.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("test,1", r.get("trace")); + }, getSourceFile(ConstructorOverloadWithFieldInitializer.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -280,6 +405,15 @@ public class OverloadTests extends AbstractTest { }, getSourceFile(OverLoadClassAndObject.class)); } + @Test + public void testOverloadClassAndObjectWithoutStubMethods() { + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + }, getSourceFile(OverLoadClassAndObjectNoStubs.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); + } + @Test public void testOverloadVarargs() { transpilerTest().getTranspiler().setUsingJavaRuntime(true); @@ -288,6 +422,17 @@ public class OverloadTests extends AbstractTest { }, getSourceFile(OverLoadVarags.class)); transpilerTest().getTranspiler().setUsingJavaRuntime(false); } + + @Test + public void testOverloadVarargsWithoutStubMethods() { + transpilerTest().getTranspiler().setUsingJavaRuntime(true); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + }, getSourceFile(OverLoadVaragsNoStubs.class)); + transpilerTest().getTranspiler().setUsingJavaRuntime(false); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); + } @Test public void testConstructorOverloadWithArray() { @@ -295,6 +440,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertTrue("1,2,3,4,3".equals(r.get("trace")) || "1,2,3,4,4".equals(r.get("trace"))); }, getSourceFile(ConstructorOverLoadWithArray.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + assertTrue("1,2,3,4,3".equals(r.get("trace")) || "1,2,3,4,4".equals(r.get("trace"))); + }, getSourceFile(ConstructorOverLoadWithArray.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -302,6 +453,11 @@ public class OverloadTests extends AbstractTest { eval(ModuleKind.none, (logHandler, r) -> { logHandler.assertNoProblems(); }, getSourceFile(LocalVariablesNameCollision.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + }, getSourceFile(LocalVariablesNameCollision.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -310,6 +466,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertEquals("1,2,3,4", r.get("trace")); }, getSourceFile(OverloadWithEnums.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("1,2,3,4", r.get("trace")); + }, getSourceFile(OverloadWithEnums.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -318,6 +480,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); assertEquals("1,2,3,3", r.get("trace")); }, getSourceFile(OverloadWithInterfaces.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("1,2,3,3", r.get("trace")); + }, getSourceFile(OverloadWithInterfaces.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -331,6 +499,17 @@ public class OverloadTests extends AbstractTest { + "m_overload_class;OverLoadWithClassParam;4;0," // + "m_overload_class;OverLoadWithClassParam;10;100", r.get("trace")); }, getSourceFile(OverLoadWithClassParam.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("ctor_overload_class;OverLoadWithClassParam;0;0," // + + "ctor_overload_class;OverLoadWithClassParam;4;0," // + + "ctor_overload_class;OverLoadWithClassParam;10;100," // + + "m_overload_class;OverLoadWithClassParam;0;0," // + + "m_overload_class;OverLoadWithClassParam;4;0," // + + "m_overload_class;OverLoadWithClassParam;10;100", r.get("trace")); + }, getSourceFile(OverLoadWithClassParam.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -338,6 +517,11 @@ public class OverloadTests extends AbstractTest { transpile(ModuleKind.none, (logHandler) -> { logHandler.assertNoProblems(); }, getSourceFile(WithAmbients.class), getSourceFile(AmbientWithOverload.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + transpile(ModuleKind.none, (logHandler) -> { + logHandler.assertNoProblems(); + }, getSourceFile(WithAmbients.class), getSourceFile(AmbientWithOverload.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -345,6 +529,11 @@ public class OverloadTests extends AbstractTest { transpile(ModuleKind.none, (logHandler) -> { logHandler.assertNoProblems(); }, getSourceFile(AbstractMethodOverloadInAnonymousClass.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + transpile(ModuleKind.none, (logHandler) -> { + logHandler.assertNoProblems(); + }, getSourceFile(AbstractMethodOverloadInAnonymousClass.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -353,6 +542,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); }, getSourceFile(A1.class), getSourceFile(A2.class), getSourceFile(A3.class), getSourceFile(F1.class), getSourceFile(F.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + transpile((logHandler) -> { + logHandler.assertNoProblems(); + }, getSourceFile(A1.class), getSourceFile(A2.class), getSourceFile(A3.class), getSourceFile(F1.class), + getSourceFile(F.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -362,6 +557,13 @@ public class OverloadTests extends AbstractTest { }, getSourceFile(source.overload.visitor2.b.A1.class), getSourceFile(source.overload.visitor2.c.A2.class), getSourceFile(source.overload.visitor2.c.A3.class), getSourceFile(source.overload.visitor2.a.F1.class), getSourceFile(source.overload.visitor2.a.F.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + transpile((logHandler) -> { + logHandler.assertNoProblems(); + }, getSourceFile(source.overload.visitor2.b.A1.class), getSourceFile(source.overload.visitor2.c.A2.class), + getSourceFile(source.overload.visitor2.c.A3.class), getSourceFile(source.overload.visitor2.a.F1.class), + getSourceFile(source.overload.visitor2.a.F.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -371,6 +573,13 @@ public class OverloadTests extends AbstractTest { assertEquals("1.1(24,7):1.2(6):1.3(true):2.1(24,7):2.2(6):2.3(true):3.1(24,7):3.2(6):3.3(true)", r.get("trace")); }, getSourceFile(WrongOverloadConstructor.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + assertEquals("1.1(24,7):1.2(6):1.3(true):2.1(24,7):2.2(6):2.3(true):3.1(24,7):3.2(6):3.3(true)", + r.get("trace")); + }, getSourceFile(WrongOverloadConstructor.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -378,6 +587,11 @@ public class OverloadTests extends AbstractTest { eval(ModuleKind.none, (logHandler, r) -> { logHandler.assertNoProblems(); }, getSourceFile(WrongOverloadConstructor2.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, r) -> { + logHandler.assertNoProblems(); + }, getSourceFile(WrongOverloadConstructor2.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -424,6 +638,12 @@ public class OverloadTests extends AbstractTest { logHandler.assertNoProblems(); }, getSourceFile(AnInterfaceWithDefaultOverloadedMethods.class), getSourceFile(AClassImplementingInterfaceWithDefaultOverloadedMethods.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval((logHandler, result) -> { + logHandler.assertNoProblems(); + }, getSourceFile(AnInterfaceWithDefaultOverloadedMethods.class), + getSourceFile(AClassImplementingInterfaceWithDefaultOverloadedMethods.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } @Test @@ -431,6 +651,11 @@ public class OverloadTests extends AbstractTest { eval(ModuleKind.none, (logHandler, result) -> { logHandler.assertNoProblems(); }, getSourceFile(SuperClass.class), getSourceFile(SubClass.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(false); + eval(ModuleKind.none, (logHandler, result) -> { + logHandler.assertNoProblems(); + }, getSourceFile(SuperClass.class), getSourceFile(SubClass.class)); + transpilerTest().getTranspiler().setGenerateOverloadStubs(true); } } diff --git a/transpiler/src/test/java/source/overload/OverLoadClassAndObjectNoStubs.java b/transpiler/src/test/java/source/overload/OverLoadClassAndObjectNoStubs.java new file mode 100644 index 00000000..1283f6ce --- /dev/null +++ b/transpiler/src/test/java/source/overload/OverLoadClassAndObjectNoStubs.java @@ -0,0 +1,62 @@ +package source.overload; + +import static jsweet.util.Lang.$apply; +import static jsweet.util.Lang.object; + +public class OverLoadClassAndObjectNoStubs { + + public static void main(String[] args) { + OverLoadClassAndObjectNoStubs overload = new OverLoadClassAndObjectNoStubs(); + + System.out.println(overload.m(AnInterface.class)); + System.out.println(overload.m(new AClass())); + System.out.println((String)$apply(object(overload).$get("m$source_overload_AnInterface"), new AClass())); + System.out.println((String)$apply(object(overload).$get("m$java_lang_Class"), AClass.class)); + // Overload with strings cannot work because AnInterface.class is transpiled as a string + System.out.println((String)$apply(object(overload).$get("m$java_lang_Class"), 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$source_overload_AClass"), new AClass())); + System.out.println((String)$apply(object(overload).$get("m2$java_lang_Class"), AClass.class)); + + assert overload.m(AnInterface.class) == "2:source.overload.AnInterface"; + assert overload.m(new AClass()) == "1:object"; + assert $apply(object(overload).$get("m$source_overload_AnInterface"), new AClass()) == "1:object"; + assert $apply(object(overload).$get("m$java_lang_Class"), AClass.class) == "2:source.overload.AClass"; + assert $apply(object(overload).$get("m$java_lang_Class"), 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$source_overload_AClass"), new AClass()) == "1:object"; + assert $apply(object(overload).$get("m2$java_lang_Class"), AClass.class) == "2:source.overload.AClass"; + + } + + String m(AnInterface o) { + return "1:" + o.getName(); + } + + String m(Class clazz) { + return "2:" + clazz.getName(); + } + + String m2(AClass o) { + return "1:" + o.getName(); + } + + String m2(Class clazz) { + return "2:" + clazz.getName(); + } + +} + +interface AnInterface { + String getName(); +} + +class AClass implements AnInterface { + public String getName() { + return "object"; + } +} \ No newline at end of file diff --git a/transpiler/src/test/java/source/overload/OverLoadVaragsNoStubs.java b/transpiler/src/test/java/source/overload/OverLoadVaragsNoStubs.java new file mode 100644 index 00000000..604df4d5 --- /dev/null +++ b/transpiler/src/test/java/source/overload/OverLoadVaragsNoStubs.java @@ -0,0 +1,50 @@ +package source.overload; + +import static jsweet.util.Lang.$insert; + +public class OverLoadVaragsNoStubs { + + public static void main(String[] args) { + OverLoadVaragsNoStubs ov = new OverLoadVaragsNoStubs(); + 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$source_overload_AnInterface2(new AClass2())")); + System.out.println((String)$insert("ov.m$source_overload_AnInterface2$boolean$java_lang_String_A(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$source_overload_AnInterface2(new AClass2())") == "1:object"; + assert $insert("ov.m$source_overload_AnInterface2$boolean$java_lang_String_A(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"; + } +} diff --git a/transpiler/src/test/java/source/overload/WrongOverloadWithInheritance.java b/transpiler/src/test/java/source/overload/WrongOverloadWithInheritance.java index 1cf07b8b..75849bb3 100644 --- a/transpiler/src/test/java/source/overload/WrongOverloadWithInheritance.java +++ b/transpiler/src/test/java/source/overload/WrongOverloadWithInheritance.java @@ -26,6 +26,18 @@ public class WrongOverloadWithInheritance { } +class C01 { + void m(String s) { + + }; +} + +class C02 extends C01 { + void m(int s) { + + }; +} + interface MyInterface { void overloaded(T arg);