various fixes for modules - to make J4TS compile with a raw module option

This commit is contained in:
Renaud Pawlak 2021-02-27 08:43:00 +01:00
parent dc444a7396
commit 4afc8ee5b0
5 changed files with 108 additions and 12 deletions

View File

@ -1300,7 +1300,11 @@ public class JSweetContext extends Context {
}
return false;
}
public boolean elementHasAnnotationType(Element element, String... annotationTypes) {
return hasAnnotationType((Symbol)element, annotationTypes);
}
/**
* Tells if the given symbol is annotated with one of the given annotation
* types.

View File

@ -605,7 +605,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
private void useModule(boolean require, boolean direct, PackageElement targetPackage, JCTree sourceTree,
String targetName, String moduleName, Symbol sourceElement) {
if (context.useModules) {
if (context.useModules && targetPackage != null) {
context.packageDependencies.add((PackageSymbol) targetPackage);
context.packageDependencies.add(compilationUnit.packge);
context.packageDependencies.addEdge(compilationUnit.packge, (PackageSymbol) targetPackage);
@ -1802,6 +1802,9 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
scanner.scan(defaultMethod.typarams);
scanner.scan(defaultMethod.recvparam);
} else {
if (defaultMethod.getName().toString().equals("forEach")) {
System.out.println();
}
scanner.scan(defaultMethod);
}
}
@ -6504,6 +6507,17 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
checkType(t.type.tsym);
}
}
// Check the owner of invoked static methods since those may be statically imported
if (t instanceof JCMethodInvocation) {
JCMethodInvocation inv = (JCMethodInvocation) t;
if (inv.meth instanceof JCIdent && ((JCIdent)inv.meth).sym instanceof MethodSymbol) {
MethodSymbol sym = (MethodSymbol)((JCIdent)inv.meth).sym;
if (sym.isStatic()) {
checkType(sym.owner);
}
}
}
super.scan(t);
}

View File

@ -34,6 +34,12 @@ public class ModuleImportDescriptor {
this.pathToImportedClass = pathToImportedClass;
}
public ModuleImportDescriptor(String importedName, String pathToImportedClass) {
super();
this.importedName = importedName;
this.pathToImportedClass = pathToImportedClass;
}
public ModuleImportDescriptor(boolean direct, PackageElement targetPackage, String importedName,
String pathToImportedClass) {
this(targetPackage, importedName, pathToImportedClass);

View File

@ -1435,16 +1435,59 @@ public class Java2TypeScriptAdapter extends PrinterAdapter {
protected final void delegateToEmulLayer(String targetClassName, String targetMethodName,
InvocationElement invocation) {
print("javaemul.internal." + targetClassName.substring(10) + "Helper.").print(targetMethodName).print("(")
.printArgList(invocation.getArguments()).print(")");
String helperClassName = targetClassName.substring(10) + "Helper";
if (context.useModules) {
String pathToImportedClass = util().getRelativePath(
"@/" + getCompilationUnit().getPackage().toString().replace('.', '/'),
("@/javaemul.internal." + helperClassName).replace('.', '/'));
if (!pathToImportedClass.startsWith(".")) {
pathToImportedClass = "./" + pathToImportedClass;
}
useModule(new ModuleImportDescriptor(helperClassName, pathToImportedClass));
print(helperClassName).print(".").print(targetMethodName).print("(")
.printArgList(invocation.getArguments()).print(")");
} else {
print("javaemul.internal." + helperClassName).print(".").print(targetMethodName).print("(")
.printArgList(invocation.getArguments()).print(")");
}
}
protected final void delegateToEmulLayerStatic(String targetClassName, String targetMethodName,
ExtendedElement target) {
print("javaemul.internal." + targetClassName.substring(10) + "Helper.").print(targetMethodName).print("(");
printTarget(target).print(")");
String helperClassName = targetClassName.substring(10) + "Helper";
if (context.useModules) {
String pathToImportedClass = util().getRelativePath(
"@/" + getCompilationUnit().getPackage().toString().replace('.', '/'),
("@/javaemul.internal." + helperClassName).replace('.', '/'));
if (!pathToImportedClass.startsWith(".")) {
pathToImportedClass = "./" + pathToImportedClass;
}
useModule(new ModuleImportDescriptor(helperClassName, pathToImportedClass));
print(helperClassName).print(".").print(targetMethodName).print("(");
printTarget(target).print(")");
} else {
print("javaemul.internal." + helperClassName).print(".").print(targetMethodName).print("(");
printTarget(target).print(")");
}
}
protected final void delegateToEmulLayer(String targetClassName, VariableAccessElement fieldAccess) {
String helperClassName = targetClassName.substring(10) + "Helper";
if (context.useModules) {
String pathToImportedClass = util().getRelativePath(
"@/" + getCompilationUnit().getPackage().toString().replace('.', '/'),
("@/javaemul.internal." + helperClassName).replace('.', '/'));
if (!pathToImportedClass.startsWith(".")) {
pathToImportedClass = "./" + pathToImportedClass;
}
useModule(new ModuleImportDescriptor(helperClassName, pathToImportedClass));
print(helperClassName).print(".").print(fieldAccess.getVariableName());
} else {
print("javaemul.internal." + helperClassName).print(".").print(fieldAccess.getVariableName());
}
}
protected final void printCastMethodInvocation(InvocationElement invocation) {
boolean needsParens = getPrinter().getParent() instanceof JCMethodInvocation;
if (needsParens) {
@ -1595,10 +1638,6 @@ public class Java2TypeScriptAdapter extends PrinterAdapter {
return super.substituteVariableAccess(variableAccess);
}
protected final void delegateToEmulLayer(String targetClassName, VariableAccessElement fieldAccess) {
print("javaemul.internal." + targetClassName.substring(10) + "Helper.").print(fieldAccess.getVariableName());
}
@Override
public boolean substituteNewClass(NewClassElement newClassElement) {
JCNewClass newClass = ((NewClassElementSupport) newClassElement).getTree();
@ -1647,7 +1686,7 @@ public class Java2TypeScriptAdapter extends PrinterAdapter {
print(context.getLangTypeMappings().get(identifier.type.toString()));
return true;
}
if (identifier.type.toString().startsWith("java.lang.")) {
if (!context.useModules && identifier.type.toString().startsWith("java.lang.")) {
if (("java.lang." + identifier.toString()).equals(identifier.type.toString())) {
// it is a java.lang class being referenced, so we expand
// its name
@ -1659,6 +1698,23 @@ public class Java2TypeScriptAdapter extends PrinterAdapter {
return super.substituteIdentifier(identifierElement);
}
@Override
public boolean substituteExtends(TypeElement type) {
// J4TS hack to avoid name clash between date classes (should be solved automatically)
if ("java.sql.Date".equals(type.getQualifiedName().toString())) {
String pathToImportedClass = util().getRelativePath(
"@/" + getCompilationUnit().getPackage().toString().replace('.', '/'),
("@/" + Date.class.getName()).replace('.', '/'));
if (!pathToImportedClass.startsWith(".")) {
pathToImportedClass = "./" + pathToImportedClass;
}
useModule(new ModuleImportDescriptor("Date as java_util_Date", pathToImportedClass));
print(" extends java_util_Date");
return true;
}
return super.substituteExtends(type);
}
@Override
public Set<String> getErasedTypes() {
return context.getLangTypeMappings().keySet();

View File

@ -28,6 +28,7 @@ import java.util.function.BiFunction;
import java.util.stream.Collectors;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Name;
import javax.lang.model.element.PackageElement;
@ -35,6 +36,7 @@ import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;
@ -43,6 +45,7 @@ import org.jsweet.JSweetConfig;
import org.jsweet.transpiler.JSweetContext;
import org.jsweet.transpiler.JSweetOptions;
import org.jsweet.transpiler.JSweetProblem;
import org.jsweet.transpiler.Java2TypeScriptTranslator;
import org.jsweet.transpiler.ModuleImportDescriptor;
import org.jsweet.transpiler.OverloadScanner.Overload;
import org.jsweet.transpiler.model.ArrayAccessElement;
@ -836,6 +839,16 @@ public class PrinterAdapter {
: parentAdapter.needsImport(importElement, qualifiedName);
}
/**
* Ensures that the current file imports the given module (will have no effects when not using modules).
*
* @param moduleImport a module import descriptor
*/
public void useModule(ModuleImportDescriptor moduleImport) {
((Java2TypeScriptTranslator)getPrinter()).useModule(moduleImport);
}
/**
* This method implements the default behavior to generate module imports.
* It may be overridden by subclasses to implement specific behaviors.
@ -869,7 +882,10 @@ public class PrinterAdapter {
importedClass = (ClassSymbol) importedClass.getEnclosingElement();
}
if (parent != null && !hasAnnotationType(importedClass, JSweetConfig.ANNOTATION_ERASED)) {
if (parent != null && !hasAnnotationType(importedClass, JSweetConfig.ANNOTATION_ERASED)
&& !(importedClass.getKind() == ElementKind.ANNOTATION_TYPE
&& !context.elementHasAnnotationType(importedClass, JSweetConfig.ANNOTATION_DECORATOR))) {
// '@' represents a common root in case there is no common
// root
// package => pathToImportedClass cannot be null because of