add an option to disable overload stubs (overloads shall be called directly with the full name)

This commit is contained in:
Renaud Pawlak 2021-01-10 21:47:59 +01:00
parent 11e4b53f6d
commit a49a504210
10 changed files with 488 additions and 44 deletions

View File

@ -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.
* </pre>
*
* @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);

View File

@ -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();
}

View File

@ -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<String> 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;
}
}

View File

@ -1842,17 +1842,19 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
context.grabMethodsToBeImplemented(methods, t.tsym);
}
methods.sort((m1, m2) -> m1.getSimpleName().compareTo(m2.getSimpleName()));
Map<Name, String> signatures = new HashMap<>();
Set<String> signatures = new HashSet<String>();
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<String> generatedVariableNames = getGeneratedVariableNames();

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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.<String>get("res2"));
assertEquals("s22", result.<String>get("res3"));
}, getSourceFile(Overload.class));
transpilerTest().getTranspiler().setGenerateOverloadStubs(false);
eval((logHandler, result) -> {
logHandler.assertNoProblems();
assertEquals("default1", result.<String>get("res1"));
assertEquals("s11", result.<String>get("res2"));
assertEquals("s22", result.<String>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);
}
}

View File

@ -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<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 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";
}
}

View File

@ -26,6 +26,18 @@ public class WrongOverloadWithInheritance {
}
class C01 {
void m(String s) {
};
}
class C02 extends C01 {
void m(int s) {
};
}
interface MyInterface<T> {
void overloaded(T arg);