mirror of
https://github.com/cincheo/jsweet.git
synced 2025-12-15 15:29:22 +00:00
avoid initialization duplication in constructors and improve generated code formatting
This commit is contained in:
parent
b5a4795a34
commit
3b732fc9fc
@ -24,6 +24,9 @@ import java.util.Set;
|
|||||||
|
|
||||||
import javax.lang.model.element.ElementKind;
|
import javax.lang.model.element.ElementKind;
|
||||||
|
|
||||||
|
import org.jsweet.transpiler.util.Util;
|
||||||
|
|
||||||
|
import com.sun.tools.javac.code.Symbol;
|
||||||
import com.sun.tools.javac.code.Symbol.VarSymbol;
|
import com.sun.tools.javac.code.Symbol.VarSymbol;
|
||||||
import com.sun.tools.javac.tree.JCTree;
|
import com.sun.tools.javac.tree.JCTree;
|
||||||
import com.sun.tools.javac.tree.JCTree.JCAssign;
|
import com.sun.tools.javac.tree.JCTree.JCAssign;
|
||||||
@ -43,7 +46,27 @@ import com.sun.tools.javac.tree.TreeScanner;
|
|||||||
public class ConstAnalyzer extends TreeScanner {
|
public class ConstAnalyzer extends TreeScanner {
|
||||||
|
|
||||||
private Set<VarSymbol> modifiedVariables = new HashSet<>();
|
private Set<VarSymbol> modifiedVariables = new HashSet<>();
|
||||||
|
private ElementKind variableKind = ElementKind.LOCAL_VARIABLE;
|
||||||
|
private boolean initializationOnly = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a constant variable analyzer on local variables only (default).
|
||||||
|
*/
|
||||||
|
public ConstAnalyzer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a constant variable analyzer on the given kind of variable.
|
||||||
|
*
|
||||||
|
* @param variableKind the variable kind to analyze (if null, analyzes all kinds
|
||||||
|
* of variables)
|
||||||
|
* @param initializationOnly only takes into account direct assignments and not self-dependent modifications
|
||||||
|
*/
|
||||||
|
public ConstAnalyzer(ElementKind variableKind, boolean initializationOnly) {
|
||||||
|
this.variableKind = variableKind;
|
||||||
|
this.initializationOnly = initializationOnly;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all the local variables that are modified within the program. All other
|
* Gets all the local variables that are modified within the program. All other
|
||||||
* local variables can be assumed as constant.
|
* local variables can be assumed as constant.
|
||||||
@ -53,20 +76,24 @@ public class ConstAnalyzer extends TreeScanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void registerModification(JCTree tree) {
|
private void registerModification(JCTree tree) {
|
||||||
if (tree instanceof JCIdent && ((JCIdent) tree).sym.getKind() == ElementKind.LOCAL_VARIABLE) {
|
Symbol symbol = Util.getAccessedSymbol(tree);
|
||||||
modifiedVariables.add((VarSymbol) ((JCIdent) tree).sym);
|
if (symbol != null && (variableKind == null || symbol.getKind() == variableKind)) {
|
||||||
|
modifiedVariables.add((VarSymbol) symbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitAssign(JCAssign assign) {
|
public void visitAssign(JCAssign assign) {
|
||||||
|
// TODO: should check if rhs contains self reference for initialization only
|
||||||
registerModification(assign.lhs);
|
registerModification(assign.lhs);
|
||||||
super.visitAssign(assign);
|
super.visitAssign(assign);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitAssignop(JCAssignOp assignOp) {
|
public void visitAssignop(JCAssignOp assignOp) {
|
||||||
registerModification(assignOp.lhs);
|
if (!this.initializationOnly) {
|
||||||
|
registerModification(assignOp.lhs);
|
||||||
|
}
|
||||||
super.visitAssignop(assignOp);
|
super.visitAssignop(assignOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +104,9 @@ public class ConstAnalyzer extends TreeScanner {
|
|||||||
case POSTINC:
|
case POSTINC:
|
||||||
case PREDEC:
|
case PREDEC:
|
||||||
case POSTDEC:
|
case POSTDEC:
|
||||||
registerModification(unary.arg);
|
if (!this.initializationOnly) {
|
||||||
|
registerModification(unary.arg);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
super.visitUnary(unary);
|
super.visitUnary(unary);
|
||||||
|
|||||||
@ -1677,7 +1677,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
String prefix = getClassName(classdecl.sym) + ".";
|
String prefix = getClassName(classdecl.sym) + ".";
|
||||||
|
|
||||||
printIndent().print("static __static_initialize() { ");
|
printIndent().print("static __static_initialize() { ");
|
||||||
print("if(!" + prefix + "__static_initialized) { ");
|
print("if (!" + prefix + "__static_initialized) { ");
|
||||||
print(prefix + "__static_initialized = true; ");
|
print(prefix + "__static_initialized = true; ");
|
||||||
for (int i = 0; i < liCount; i++) {
|
for (int i = 0; i < liCount; i++) {
|
||||||
print(prefix + "__static_initializer_" + i + "(); ");
|
print(prefix + "__static_initializer_" + i + "(); ");
|
||||||
@ -1709,7 +1709,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (JCTree def : defs) {
|
for (JCTree def : defs) {
|
||||||
if(injectedDefaultMethods.contains(def)) {
|
if (injectedDefaultMethods.contains(def)) {
|
||||||
JCMethodDecl defaultMethod = (JCMethodDecl) def;
|
JCMethodDecl defaultMethod = (JCMethodDecl) def;
|
||||||
MethodSymbol s = injectedDefaultMethodMap.get(defaultMethod);
|
MethodSymbol s = injectedDefaultMethodMap.get(defaultMethod);
|
||||||
getScope().defaultMethodScope = true;
|
getScope().defaultMethodScope = true;
|
||||||
@ -2142,11 +2142,11 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
case JSweetConfig.NEW_FUNCTION_NAME:
|
case JSweetConfig.NEW_FUNCTION_NAME:
|
||||||
return "new";
|
return "new";
|
||||||
default:
|
default:
|
||||||
if (context.hasMethodNameMapping(methodDecl.sym)) {
|
if (context.hasMethodNameMapping(methodDecl.sym)) {
|
||||||
return context.getMethodNameMapping(methodDecl.sym);
|
return context.getMethodNameMapping(methodDecl.sym);
|
||||||
} else {
|
} else {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2595,7 +2595,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
print(" else ");
|
print(" else ");
|
||||||
}
|
}
|
||||||
wasPrinted = true;
|
wasPrinted = true;
|
||||||
print("if(");
|
print("if (");
|
||||||
printMethodParamsTest(overload, method);
|
printMethodParamsTest(overload, method);
|
||||||
print(") ");
|
print(") ");
|
||||||
if (method.sym.isConstructor()
|
if (method.sym.isConstructor()
|
||||||
@ -2837,24 +2837,24 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
print(";").println();
|
print(";").println();
|
||||||
} else if (var.init == null) {
|
} else if (var.init == null) {
|
||||||
if (doesMemberNameRequireQuotes(name)) {
|
if (doesMemberNameRequireQuotes(name)) {
|
||||||
printIndent().print("if(").print("this['").print(name).print("']").print("===undefined) ");
|
printIndent().print("if (").print("this['").print(name).print("']").print(" === undefined) { ");
|
||||||
if (context.options.isNonEnumerableTransients() && var.sym.getModifiers().contains(Modifier.TRANSIENT)) {
|
if (context.options.isNonEnumerableTransients() && var.sym.getModifiers().contains(Modifier.TRANSIENT)) {
|
||||||
print("Object.defineProperty(this, " + getStringLiteralQuote() + name + getStringLiteralQuote()
|
print("Object.defineProperty(this, " + getStringLiteralQuote() + name + getStringLiteralQuote()
|
||||||
+ ", { value: ").print(getAdapter().getVariableInitialValue(var.sym))
|
+ ", { value: ").print(getAdapter().getVariableInitialValue(var.sym))
|
||||||
.print(", enumerable: false });").println();
|
.print(", enumerable: false }); }").println();
|
||||||
} else {
|
} else {
|
||||||
print("this['").print(name).print("'] = ").print(getAdapter().getVariableInitialValue(var.sym))
|
print("this['").print(name).print("'] = ").print(getAdapter().getVariableInitialValue(var.sym))
|
||||||
.print(";").println();
|
.print("; }").println();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printIndent().print("if(").print("this.").print(name).print("===undefined) ");
|
printIndent().print("if (").print("this.").print(name).print(" === undefined) { ");
|
||||||
if (context.options.isNonEnumerableTransients() && var.sym.getModifiers().contains(Modifier.TRANSIENT)) {
|
if (context.options.isNonEnumerableTransients() && var.sym.getModifiers().contains(Modifier.TRANSIENT)) {
|
||||||
print("Object.defineProperty(this, " + getStringLiteralQuote() + name + getStringLiteralQuote()
|
print("Object.defineProperty(this, " + getStringLiteralQuote() + name + getStringLiteralQuote()
|
||||||
+ ", { value: ").print(getAdapter().getVariableInitialValue(var.sym))
|
+ ", { value: ").print(getAdapter().getVariableInitialValue(var.sym))
|
||||||
.print(", enumerable: false });").println();
|
.print(", enumerable: false }); }").println();
|
||||||
} else {
|
} else {
|
||||||
print("this.").print(name).print(" = ").print(getAdapter().getVariableInitialValue(var.sym))
|
print("this.").print(name).print(" = ").print(getAdapter().getVariableInitialValue(var.sym))
|
||||||
.print(";").println();
|
.print("; }").println();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2927,7 +2927,6 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
}
|
}
|
||||||
if (method.getBody() != null) {
|
if (method.getBody() != null) {
|
||||||
boolean skipFirst = false;
|
boolean skipFirst = false;
|
||||||
boolean initialized = false;
|
|
||||||
if (!method.getBody().stats.isEmpty() && method.getBody().stats.get(0).toString().startsWith("this(")) {
|
if (!method.getBody().stats.isEmpty() && method.getBody().stats.get(0).toString().startsWith("this(")) {
|
||||||
skipFirst = true;
|
skipFirst = true;
|
||||||
JCMethodInvocation inv = (JCMethodInvocation) ((JCExpressionStatement) method.getBody().stats
|
JCMethodInvocation inv = (JCMethodInvocation) ((JCExpressionStatement) method.getBody().stats
|
||||||
@ -2937,7 +2936,6 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
for (JCMethodDecl md : overload.methods) {
|
for (JCMethodDecl md : overload.methods) {
|
||||||
if (md.sym.equals(ms)) {
|
if (md.sym.equals(ms)) {
|
||||||
printIndent();
|
printIndent();
|
||||||
initialized = true;
|
|
||||||
printInlinedMethod(overload, md, inv.args);
|
printInlinedMethod(overload, md, inv.args);
|
||||||
println();
|
println();
|
||||||
}
|
}
|
||||||
@ -2954,19 +2952,17 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
enter(method.getBody());
|
enter(method.getBody());
|
||||||
com.sun.tools.javac.util.List<JCStatement> stats = skipFirst ? method.getBody().stats.tail
|
com.sun.tools.javac.util.List<JCStatement> stats = skipFirst ? method.getBody().stats.tail
|
||||||
: method.getBody().stats;
|
: method.getBody().stats;
|
||||||
|
if (method.sym.isConstructor()) {
|
||||||
|
getScope().hasDeclaredConstructor = true;
|
||||||
|
}
|
||||||
if (!stats.isEmpty() && stats.head.toString().startsWith("super(")) {
|
if (!stats.isEmpty() && stats.head.toString().startsWith("super(")) {
|
||||||
printBlockStatement(stats.head);
|
printBlockStatement(stats.head);
|
||||||
printFieldInitializations();
|
printFieldInitializations(stats);
|
||||||
if (!initialized) {
|
|
||||||
printInstanceInitialization(getParent(JCClassDecl.class), method.sym);
|
|
||||||
}
|
|
||||||
if (!stats.tail.isEmpty()) {
|
if (!stats.tail.isEmpty()) {
|
||||||
printBlockStatements(stats.tail);
|
printBlockStatements(stats.tail);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!initialized) {
|
printFieldInitializations(stats);
|
||||||
printInstanceInitialization(getParent(JCClassDecl.class), method.sym);
|
|
||||||
}
|
|
||||||
if (!stats.isEmpty() || !method.sym.isConstructor()) {
|
if (!stats.isEmpty() || !method.sym.isConstructor()) {
|
||||||
printIndent();
|
printIndent();
|
||||||
}
|
}
|
||||||
@ -3008,24 +3004,24 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
endIndent().printIndent().print("}");
|
endIndent().printIndent().print("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printFieldInitializations() {
|
private void printFieldInitializations(List<JCStatement> potentialInitializationStatements) {
|
||||||
JCClassDecl clazz = getParent(JCClassDecl.class);
|
JCClassDecl clazz = getParent(JCClassDecl.class);
|
||||||
for (JCTree t : clazz.getMembers()) {
|
for (JCTree t : clazz.getMembers()) {
|
||||||
if (t instanceof JCVariableDecl && !getScope().fieldsWithInitializers.contains(t)) {
|
if (t instanceof JCVariableDecl && !getScope().fieldsWithInitializers.contains(t)) {
|
||||||
JCVariableDecl field = (JCVariableDecl) t;
|
JCVariableDecl field = (JCVariableDecl) t;
|
||||||
if (!field.sym.isStatic() && !context.hasAnnotationType(field.sym, JSweetConfig.ANNOTATION_ERASED)) {
|
if (!field.sym.isStatic() && !context.hasAnnotationType(field.sym, JSweetConfig.ANNOTATION_ERASED)) {
|
||||||
String name = getIdentifier(field.sym);
|
String name = getIdentifier(field.sym);
|
||||||
if (context.getFieldNameMapping(field.sym) != null) {
|
if (context.getFieldNameMapping(field.sym) != null) {
|
||||||
name = context.getFieldNameMapping(field.sym);
|
name = context.getFieldNameMapping(field.sym);
|
||||||
}
|
}
|
||||||
printIndent().print("if(").print("this.").print(name).print("===undefined) ");
|
printIndent().print("if (").print("this.").print(name).print(" === undefined) { ");
|
||||||
if (context.options.isNonEnumerableTransients() && field.sym.getModifiers().contains(Modifier.TRANSIENT)) {
|
if (context.options.isNonEnumerableTransients() && field.sym.getModifiers().contains(Modifier.TRANSIENT)) {
|
||||||
print("Object.defineProperty(this, " + getStringLiteralQuote() + name + getStringLiteralQuote()
|
print("Object.defineProperty(this, " + getStringLiteralQuote() + name + getStringLiteralQuote()
|
||||||
+ ", { value: ").print(getAdapter().getVariableInitialValue(field.sym))
|
+ ", { value: ").print(getAdapter().getVariableInitialValue(field.sym))
|
||||||
.print(", enumerable: false });");
|
.print(", enumerable: false }); }").println();
|
||||||
} else {
|
} else {
|
||||||
print("this.").print(name).print(" = ").print(getAdapter().getVariableInitialValue(field.sym))
|
print("this.").print(name).print(" = ").print(getAdapter().getVariableInitialValue(field.sym))
|
||||||
.print(";").println();
|
.print("; }").println();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3513,7 +3509,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (varDecl.init != null && !isDefinitionScope) {
|
if (varDecl.init != null && !isDefinitionScope) {
|
||||||
print("if(" + prefix).print(name).print(" == null) ").print(prefix).print(name).print(" = ");
|
print("if (" + prefix).print(name).print(" == null) { ").print(prefix).print(name).print(" = ");
|
||||||
/*
|
/*
|
||||||
* if (getScope().enumWrapperClassScope) { JCNewClass newClass = (JCNewClass)
|
* if (getScope().enumWrapperClassScope) { JCNewClass newClass = (JCNewClass)
|
||||||
* varDecl.init; print("new "
|
* varDecl.init; print("new "
|
||||||
@ -3524,7 +3520,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
print(varDecl.init);
|
print(varDecl.init);
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
print("; ");
|
print("; }");
|
||||||
}
|
}
|
||||||
print("return ").print(prefix).print(name).print("; }");
|
print("return ").print(prefix).print(name).print("; }");
|
||||||
if (!globals && context.bundleMode) {
|
if (!globals && context.bundleMode) {
|
||||||
@ -5022,7 +5018,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitIf(JCIf ifStatement) {
|
public void visitIf(JCIf ifStatement) {
|
||||||
print("if").print(ifStatement.cond).print(" ");
|
print("if ").print(ifStatement.cond).print(" ");
|
||||||
print(ifStatement.thenpart);
|
print(ifStatement.thenpart);
|
||||||
if (!(ifStatement.thenpart instanceof JCBlock)) {
|
if (!(ifStatement.thenpart instanceof JCBlock)) {
|
||||||
if (!statementsWithNoSemis.contains(ifStatement.thenpart.getClass())) {
|
if (!statementsWithNoSemis.contains(ifStatement.thenpart.getClass())) {
|
||||||
@ -5295,7 +5291,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print("<any> (function(dims) { " + VAR_DECL_KEYWORD
|
print("<any> (function(dims) { " + VAR_DECL_KEYWORD
|
||||||
+ " allocate = function(dims) { if(dims.length==0) { return "
|
+ " allocate = function(dims) { if (dims.length === 0) { return "
|
||||||
+ Util.getTypeInitialValue(newArray.elemtype.type) + "; } else { " + VAR_DECL_KEYWORD
|
+ Util.getTypeInitialValue(newArray.elemtype.type) + "; } else { " + VAR_DECL_KEYWORD
|
||||||
+ " array = []; for(" + VAR_DECL_KEYWORD
|
+ " array = []; for(" + VAR_DECL_KEYWORD
|
||||||
+ " i = 0; i < dims[0]; i++) { array.push(allocate(dims.slice(1))); } return array; }}; return allocate(dims);})");
|
+ " i = 0; i < dims[0]; i++) { array.push(allocate(dims.slice(1))); } return array; }}; return allocate(dims);})");
|
||||||
@ -5960,8 +5956,8 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
|
|||||||
public void visitAssert(JCAssert assertion) {
|
public void visitAssert(JCAssert assertion) {
|
||||||
if (!context.options.isIgnoreAssertions()) {
|
if (!context.options.isIgnoreAssertions()) {
|
||||||
String assertCode = assertion.toString().replace("\"", "'");
|
String assertCode = assertion.toString().replace("\"", "'");
|
||||||
print("if(!(").print(assertion.cond).print(
|
print("if (!(").print(assertion.cond).print(
|
||||||
")) throw new Error(\"Assertion error line " + getCurrentLine() + ": " + assertCode + "\");");
|
")) { throw new Error(\"Assertion error line " + getCurrentLine() + ": " + assertCode + "\"); }");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user