generate human-friendly lopping variable names

This commit is contained in:
Renaud Pawlak 2021-01-06 19:00:51 +01:00
parent 4f27fb273d
commit c4584f116d
3 changed files with 134 additions and 14 deletions

View File

@ -344,6 +344,8 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
private boolean decoratorScope = false;
public Stack<ForeachLoopScope> foreachLoopContext;
private final JSweetContext context;
private final CompilationUnitTree compilationUnit;
@ -492,6 +494,17 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
}
private static class ForeachLoopScope {
public EnhancedForLoopTree loop;
public String variableName;
public String arrayName;
public ForeachLoopScope(EnhancedForLoopTree loop) {
super();
this.loop = loop;
}
}
private Stack<ClassScope> scope = new Stack<>();
private boolean isAnnotationScope = false;
@ -5196,12 +5209,71 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
return returnNothing();
}
private int getIndexVariableCount() {
return getScope().foreachLoopContext == null ? 0 : getScope().foreachLoopContext.size();
}
private Set<String> getGeneratedVariableNames() {
Set<String> names = new HashSet<>();
if (getScope().foreachLoopContext != null) {
getScope().foreachLoopContext.stream().forEach(s -> {
names.add(s.variableName);
if (s.arrayName != null) {
names.add(s.arrayName);
}
});
}
return names;
}
private int getArrayVariableCount() {
return getScope().foreachLoopContext == null ? 0
: (int) getScope().foreachLoopContext.stream().filter(s -> s.arrayName != null).count();
}
private String getFreeVariableName(String variablePrefix, int index) {
String name = variablePrefix + (index == 0 ? "" : "" + index);
Set<String> generatedVariableNames = getGeneratedVariableNames();
while (generatedVariableNames.contains(name)) {
name = variablePrefix + (++index);
}
int position = stack.size() - 2;
while (position >= 0 && !(stack.get(position) instanceof MethodTree)) {
if (stack.get(position) instanceof BlockTree) {
BlockTree block = (BlockTree) stack.get(position);
// analyze all the previous declarations in the block
for (Tree t : block.getStatements()) {
if (t == stack.get(position + 1)) {
// do not analyze post declarations
break;
}
// name clash: we try again with another index
if (t instanceof VariableTree && name.equals(((VariableTree) t).getName().toString())) {
return getFreeVariableName(variablePrefix, index + 1);
}
}
}
position--;
}
if (position >= 0 && stack.get(position) instanceof MethodTree) {
for (VariableTree param : ((MethodTree) stack.get(position)).getParameters()) {
if (name.equals(param.getName().toString())) {
return getFreeVariableName(variablePrefix, index + 1);
}
}
}
return name;
}
/**
* Prints a foreach loop tree.
*/
@Override
public Void visitEnhancedForLoop(EnhancedForLoopTree foreachLoop, Trees trees) {
String indexVarName = "index" + util().getId();
String indexVarName = getFreeVariableName("index", getIndexVariableCount());
boolean[] hasLength = { false };
TypeElement targetType = Util.getTypeElement(foreachLoop.getExpression());
TypeMirror collectionType = Util.getType(foreachLoop.getExpression());
@ -5221,20 +5293,27 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
});
}
if (!getAdapter().substituteForEachLoop(createExtendedElement(foreachLoop), hasLength[0], indexVarName)) {
boolean noVariable = foreachLoop.getExpression() instanceof IdentifierTree
if (getScope().foreachLoopContext == null) {
getScope().foreachLoopContext = new Stack<>();
}
ForeachLoopScope foreachLoopScope = new ForeachLoopScope(foreachLoop);
getScope().foreachLoopContext.push(foreachLoopScope);
boolean noVariable = foreachLoop.getExpression() instanceof IdentifierTree
|| foreachLoop.getExpression() instanceof MemberSelectTree;
if (noVariable) {
print("for(" + VAR_DECL_KEYWORD + " " + indexVarName + "=0; " + indexVarName + " < ")
foreachLoopScope.variableName = indexVarName;
if (noVariable) {
print("for(" + VAR_DECL_KEYWORD + " " + indexVarName + " = 0; " + indexVarName + " < ")
.print(foreachLoop.getExpression()).print("." + "length" + "; " + indexVarName + "++) {")
.println().startIndent().printIndent();
print(VAR_DECL_KEYWORD + " " + avoidJSKeyword(foreachLoop.getVariable().getName().toString()) + " = ")
.print(foreachLoop.getExpression()).print("[" + indexVarName + "];").println();
} else {
String arrayVarName = "array" + util().getId();
print("{").println().startIndent().printIndent();
String arrayVarName = getFreeVariableName("array", getArrayVariableCount());
foreachLoopScope.arrayName = arrayVarName;
print("{").println().startIndent().printIndent();
print(VAR_DECL_KEYWORD + " " + arrayVarName + " = ").print(foreachLoop.getExpression()).print(";")
.println().printIndent();
print("for(" + VAR_DECL_KEYWORD + " " + indexVarName + "=0; " + indexVarName + " < " + arrayVarName
print("for(" + VAR_DECL_KEYWORD + " " + indexVarName + " = 0; " + indexVarName + " < " + arrayVarName
+ ".length; " + indexVarName + "++) {").println().startIndent().printIndent();
print(VAR_DECL_KEYWORD + " " + avoidJSKeyword(foreachLoop.getVariable().getName().toString()) + " = "
+ arrayVarName + "[" + indexVarName + "];").println();
@ -5245,6 +5324,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
if (!noVariable) {
endIndent().println().printIndent().print("}");
}
getScope().foreachLoopContext.pop();
}
return returnNothing();

View File

@ -337,13 +337,6 @@ public class Util {
private static long id = 121;
/**
* Returns a unique id (incremental).
*/
public long getId() {
return id++;
}
/**
* Tells if the given element is within the Java sources being compiled.
*/

View File

@ -78,9 +78,56 @@ public class Looping {
lastIndex = j;
}
assert lastIndex == 602;
int[] array = new int[] { 1, 2, 3 };
int pos = 1;
for (int integer : array) {
assert integer == pos;
pos++;
}
pos = 1;
for (int integer : array) {
assert integer == pos;
pos++;
}
// nested loops
pos = 1;
for (int integer : array) {
assert integer == pos;
pos++;
int pos2 = 1;
int index1 = 4;
for (int integer2 : array) {
assert integer2 == pos2;
assert index1 == 4;
pos2++;
}
}
// test clash between iteration variable and local variable
int index = 12;
pos = 1;
for (int integer : array) {
assert index == 12;
assert integer == pos;
pos++;
}
loop(array, 14);
System.out.println("DONE Looping test");
}
public static void loop(int[] array, int index) {
int pos = 1;
for (int integer : array) {
assert index == 14;
assert integer == pos;
pos++;
}
}
int divide(int j) {
return j / 2;