use const keyword for final and effectively final variables

This commit is contained in:
Renaud Pawlak 2020-06-14 07:58:13 +02:00
parent 036f4968c8
commit 9088aa0a52
4 changed files with 128 additions and 3 deletions

View File

@ -0,0 +1,99 @@
/*
* JSweet transpiler - http://www.jsweet.org
* Copyright (C) 2015 CINCHEO SAS <renaud.pawlak@cincheo.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jsweet.transpiler;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.ElementKind;
import org.jsweet.transpiler.util.AbstractTreeScanner;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAssign;
import com.sun.tools.javac.tree.JCTree.JCAssignOp;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.JCTree.JCUnary;
/**
* This AST scanner analyzes local variables to determine if they are locally
* assigned and can be assumed constant or not.
*
* @see JSweetContext
* @author Renaud Pawlak
*/
public class ConstAnalyzer extends AbstractTreeScanner {
private Set<VarSymbol> modifiedVariables = new HashSet<>();
/**
* Gets all the local variables that are modified within the program. All other
* local variables can be assumed as constant.
*/
public Set<VarSymbol> getModifiedVariables() {
return modifiedVariables;
}
/**
* Creates a new constant variable analyzer.
*/
public ConstAnalyzer(TranspilationHandler logHandler, JSweetContext context) {
super(logHandler, context, null);
}
private void registerModification(JCTree tree) {
if (tree instanceof JCIdent && ((JCIdent) tree).sym.getKind() == ElementKind.LOCAL_VARIABLE) {
modifiedVariables.add((VarSymbol) ((JCIdent) tree).sym);
}
}
@Override
public void visitAssign(JCAssign assign) {
registerModification(assign.lhs);
super.visitAssign(assign);
}
@Override
public void visitAssignop(JCAssignOp assignOp) {
registerModification(assignOp.lhs);
}
@Override
public void visitUnary(JCUnary unary) {
switch (unary.getTag()) {
case PREINC:
case POSTINC:
case PREDEC:
case POSTDEC:
registerModification(unary.arg);
default:
}
super.visitUnary(unary);
}
public void process(List<JCCompilationUnit> compilationUnits) {
for (JCCompilationUnit compilationUnit : compilationUnits) {
scan(compilationUnit);
}
}
}

View File

@ -482,6 +482,8 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
private boolean isDefinitionScope = false;
private ConstAnalyzer constAnalyzer = null;
protected final boolean isTopLevelScope() {
return getIndent() == 0;
}
@ -736,7 +738,9 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
footer.delete(0, footer.length());
setCompilationUnit(topLevel);
constAnalyzer = new ConstAnalyzer(getLogHandler(), context);
constAnalyzer.scan(topLevel);
String packge = topLevel.packge.toString();
boolean globalModule = JSweetConfig.GLOBALS_PACKAGE_NAME.equals(packge)
@ -3404,7 +3408,12 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
if (isDefinitionScope) {
print("var ");
} else {
print(VAR_DECL_KEYWORD + " ");
if (varDecl.sym.getModifiers().contains(Modifier.FINAL) || (constAnalyzer != null
&& !constAnalyzer.getModifiedVariables().contains(varDecl.sym))) {
print("const ");
} else {
print(VAR_DECL_KEYWORD + " ");
}
}
}
} else {

View File

@ -60,7 +60,7 @@ public abstract class AbstractTreeScanner extends TreeScanner {
private TranspilationHandler logHandler;
/**
/**
* Report a JSweet problem on the given program element (tree).
*
* @param tree
@ -468,4 +468,11 @@ public abstract class AbstractTreeScanner extends TreeScanner {
return null;
}
/**
* Gets the transpilation handler for this scanner.
*/
public TranspilationHandler getLogHandler() {
return logHandler;
}
}

View File

@ -33,7 +33,11 @@ import def.js.Math;
public class FinalVariables {
int finalField;
int modifiedField;
void m1(HTMLElement e) {
modifiedField++;
NodeList nodes = document.querySelectorAll("form .form-control");
for (int i = 0; i < nodes.length; i++) {
HTMLElement element = (HTMLElement) nodes.$get(i);
@ -117,6 +121,12 @@ public class FinalVariables {
});
}
String notFinal() {
String s = "abc";
s = "bcd";
return s;
}
}
// subset of promises API