try to avoid cyclic dependencies when generating file-by-file modules (JSweet 2 catch-up 2e7ae54ac2)

This commit is contained in:
Louis Grignon 2020-09-01 17:30:09 +02:00
parent 9fe3862ac4
commit 035ac67d82
5 changed files with 47 additions and 29 deletions

View File

@ -112,6 +112,8 @@ public class JSweetContext {
}
private Map<String, TypeMirror> jdkSubclasses = new HashMap<>();
public StaticInitilializerAnalyzer referenceAnalyzer;
/**
* Maps the name of a class to the JDK type it extends.

View File

@ -837,6 +837,8 @@ public class JSweetTranspiler implements JSweetOptions, AutoCloseable {
factory.createBeforeTranslationScanner(transpilationHandler, context).process(context.compilationUnits);
if (context.useModules) {
StaticInitilializerAnalyzer analizer = new StaticInitilializerAnalyzer(context);
analizer.process(context.compilationUnits);
generateTsFiles(transpilationHandler, files, context.compilationUnits);
} else {
if (bundle) {

View File

@ -609,22 +609,33 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
// qualName.replace(".", "_")... this would work in the general
// case...
if (direct) {
context.addHeader("import." + targetName, "import " + targetName + " = " + moduleName + ";\n");
} else {
if (!context.moduleBundleMode && !(sourceElement instanceof TypeElement
&& context.referenceAnalyzer.isDependent(compilationUnit, (TypeElement) sourceElement))) {
boolean fullImport = require || GLOBALS_CLASS_NAME.equals(targetName);
if (fullImport) {
if (context.useRequireForModules) {
context.addHeader("import." + targetName,
"import " + targetName + " = require(\"" + moduleName + "\");\n");
// import as footer statements to avoid cyclic dependencies
// as much as possible
// note that the better way to avoid cyclic dependency
// issues is to create bundles
context.addTopFooterStatement("import { " + targetName + " } from '" + moduleName + "';\n");
} else {
if (direct) {
context.addHeader("import." + targetName, "import " + targetName + " = " + moduleName + ";\n");
} else {
boolean fullImport = require || GLOBALS_CLASS_NAME.equals(targetName);
if (fullImport) {
if (context.useRequireForModules) {
context.addHeader("import." + targetName,
"import " + targetName + " = require(\"" + moduleName + "\");\n");
} else {
context.addHeader("import." + targetName,
"import * as " + targetName + " from '" + moduleName + "';\n");
}
} else {
context.addHeader("import." + targetName,
"import * as " + targetName + " from '" + moduleName + "';\n");
"import { " + targetName + " } from '" + moduleName + "';\n");
}
} else {
context.addHeader("import." + targetName,
"import { " + targetName + " } from '" + moduleName + "';\n");
}
}
}
@ -1119,7 +1130,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
removeLastChars(3);
return this;
}
Element typeElement = toTypeElement(typeTree);
TypeMirror typeType = toType(typeTree);
if (typeElement instanceof TypeParameterElement) {
@ -2798,12 +2809,12 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
if (doesMemberNameRequireQuotes(name)) {
printIndent();
print("if(").print("this['").print(name).print("']").print("===undefined) ");
print("this['").print(name).print("'] = ")
.print(getAdapter().getVariableInitialValue(varElement)).print(";").println();
print("this['").print(name).print("'] = ").print(getAdapter().getVariableInitialValue(varElement))
.print(";").println();
} else {
printIndent();
print("if(").print("this.").print(name).print("===undefined) this.").print(name)
.print(" = ").print(getAdapter().getVariableInitialValue(varElement)).print(";").println();
print("if(").print("this.").print(name).print("===undefined) this.").print(name).print(" = ")
.print(getAdapter().getVariableInitialValue(varElement)).print(";").println();
}
}
}
@ -6312,7 +6323,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
ModuleImportDescriptor moduleImport = getModuleImportDescriptor(name, (TypeElement) type);
if (moduleImport != null) {
useModule(false, moduleImport.isDirect(), moduleImport.getTargetPackage(), null,
moduleImport.getImportedName(), moduleImport.getPathToImportedClass(), null);
moduleImport.getImportedName(), moduleImport.getPathToImportedClass(), type);
}
}
}

View File

@ -81,21 +81,20 @@ public class StaticInitilializerAnalyzer extends TreePathScanner<Void, Trees> {
*/
public StaticInitilializerAnalyzer(JSweetContext context) {
this.context = context;
this.context.referenceAnalyzer = this;
}
private DirectedGraph<CompilationUnitTree> getGraph() {
if (context.useModules) {
DirectedGraph<CompilationUnitTree> graph = staticInitializersDependencies
.get(currentCompilationUnit.getPackage());
if (graph == null) {
graph = new DirectedGraph<>();
staticInitializersDependencies.put(currentCompilationUnit.getPackage(), graph);
}
return graph;
} else {
return globalStaticInitializersDependencies;
}
return globalStaticInitializersDependencies;
}
public boolean isDependent(CompilationUnitTree cuSource, TypeElement target) {
CompilationUnitTree cuTarget = typesToCompilationUnits.get(target);
if (cuSource != null && cuTarget != null) {
return globalStaticInitializersDependencies.hasEdge(cuTarget, cuSource);
}
return false;
}
Set<TypeMirror> currentTopLevelImportedTypes = new HashSet<>();

View File

@ -2220,6 +2220,10 @@ public class Util {
return list.get(list.size() - 1);
}
/**
* Returns true if given element is an interface TypeElement. <br />
* WARNING: does not include JSweet @Interface
*/
public boolean isInterface(Element typeElement) {
return typeElement != null && typeElement.getKind() == ElementKind.INTERFACE;
}