Skip to content

Commit 781b39d

Browse files
committed
Reserve preserved Lua class names safely
1 parent 1eb32b2 commit 781b39d

4 files changed

Lines changed: 53 additions & 21 deletions

File tree

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/LuaTranslator.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,8 @@ protected String uniqueName(String rawName) {
331331
}
332332

333333
public LuaCompilationUnit translate() {
334-
assertNoDanglingFunctionReferences(prog);
335334
collectPredefinedNames();
335+
assertNoDanglingFunctionReferences(prog);
336336

337337
normalizeFieldNames();
338338

@@ -503,6 +503,15 @@ private void collectPredefinedNames() {
503503
}
504504
}
505505

506+
for (ImClass clazz : prog.getClasses()) {
507+
for (ImFunction function : clazz.getFunctions()) {
508+
if (NamePreservation.isPreserved(function)) {
509+
LuaFunction luaFunction = luaFunc.getFor(function);
510+
usedNames.add(luaFunction.getName());
511+
}
512+
}
513+
}
514+
506515
for (ImVar global : prog.getGlobals()) {
507516
if (global.getIsBJ()) {
508517
setNameFromTrace(global);

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/NamePreservation.java

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import de.peeeq.wurstscript.types.WurstType;
88
import de.peeeq.wurstscript.types.WurstTypeArray;
99
import de.peeeq.wurstscript.types.WurstTypeTuple;
10-
import org.eclipse.jdt.annotation.Nullable;
1110

1211
import java.util.ArrayList;
1312
import java.util.LinkedHashMap;
@@ -18,6 +17,7 @@
1817
public final class NamePreservation {
1918

2019
public static final String ANNOTATION = "@preserveName";
20+
private static final String SYNTHETIC_MARKER = "__wurst_trve_preserve_name";
2121

2222
private NamePreservation() {
2323
}
@@ -42,14 +42,14 @@ public static void preserve(ImFunction function) {
4242
* name-based side table. The marker remains attached to the AST definition and is copied to
4343
* the corresponding IM variable through its trace.
4444
*/
45-
public static @Nullable Annotation preserve(GlobalVarDef variable) {
45+
public static void preserve(GlobalVarDef variable) {
4646
if (variable.hasAnnotation(ANNOTATION)) {
47-
return null;
47+
return;
4848
}
4949
Annotation marker = Ast.Annotation(variable.getSource(),
50-
Ast.Identifier(variable.getSource(), ANNOTATION.substring(1)), Ast.Arguments());
50+
Ast.Identifier(variable.getSource(), ANNOTATION.substring(1)),
51+
Ast.Arguments(Ast.ExprStringVal(variable.getSource(), SYNTHETIC_MARKER)));
5152
variable.getModifiers().add(marker);
52-
return marker;
5353
}
5454

5555
/**
@@ -71,6 +71,21 @@ public void visit(GlobalVarDef variable) {
7171
return result;
7272
}
7373

74+
/** Removes markers synthesized for TRVE during an earlier validation run. */
75+
public static void clearSyntheticMarkers(WurstModel model) {
76+
model.accept(new Element.DefaultVisitor() {
77+
@Override
78+
public void visit(GlobalVarDef variable) {
79+
super.visit(variable);
80+
variable.getModifiers().removeIf(modifier -> modifier instanceof Annotation annotation
81+
&& annotation.getAnnotationType().equalsIgnoreCase(ANNOTATION)
82+
&& annotation.getArgs().size() == 1
83+
&& annotation.getArgs().get(0) instanceof ExprStringVal value
84+
&& value.getValS().equals(SYNTHETIC_MARKER));
85+
}
86+
});
87+
}
88+
7489
private static void addTupleComponentNames(RuntimeNameIndex index, String name, WurstType type,
7590
GlobalVarDef variable) {
7691
if (type instanceof WurstTypeArray array) {
@@ -88,26 +103,15 @@ private static void addTupleComponentNames(RuntimeNameIndex index, String name,
88103

89104
public static final class RuntimeNameIndex {
90105
private final Map<String, List<GlobalVarDef>> globalsByName = new LinkedHashMap<>();
91-
private final Map<GlobalVarDef, Annotation> syntheticMarkers = new LinkedHashMap<>();
92106

93107
private void add(String name, GlobalVarDef variable) {
94108
globalsByName.computeIfAbsent(name, ignored -> new ArrayList<>()).add(variable);
95109
}
96110

97111
public void preserve(String runtimeName) {
98112
for (GlobalVarDef variable : globalsByName.getOrDefault(runtimeName, List.of())) {
99-
Annotation marker = NamePreservation.preserve(variable);
100-
if (marker != null) {
101-
syntheticMarkers.put(variable, marker);
102-
}
103-
}
104-
}
105-
106-
public void clearSyntheticMarkers() {
107-
for (Map.Entry<GlobalVarDef, Annotation> entry : syntheticMarkers.entrySet()) {
108-
entry.getKey().getModifiers().remove(entry.getValue());
113+
NamePreservation.preserve(variable);
109114
}
110-
syntheticMarkers.clear();
111115
}
112116
}
113117

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/WurstValidator.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,7 @@ public void validate(Collection<CompilationUnit> toCheck) {
9090
guaranteedClassFieldInitCache.clear();
9191
moduleFieldCopiesCache.clear();
9292
moduleFieldCopiesIndexed = false;
93-
if (runtimeNameIndex != null) {
94-
runtimeNameIndex.clearSyntheticMarkers();
95-
}
93+
NamePreservation.clearSyntheticMarkers(prog);
9694
runtimeNameIndex = NamePreservation.indexGlobals(prog);
9795

9896
lightValidation(toCheck);

de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/OptimizerTests.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,27 @@ public void preserveNameAnnotationKeepsClassFunctionNameInLua() throws IOExcepti
587587
"Expected a preserved class function to keep its emitted name.\n" + output);
588588
}
589589

590+
@Test
591+
public void preservedClassFunctionReservesItsLuaNameBeforeClassVariables() throws IOException {
592+
test().testLua(true).luaOnly(true).executeProg(false).lines(
593+
"package test",
594+
" class Foo",
595+
" @preserveName function bar()",
596+
" skip",
597+
" class Foo_bar",
598+
" init",
599+
" new Foo_bar",
600+
"endpackage");
601+
602+
String output = Files.toString(
603+
new File("./test-output/lua/OptimizerTests_preservedClassFunctionReservesItsLuaNameBeforeClassVariables.lua"),
604+
Charsets.UTF_8);
605+
assertTrue(output.contains("function Foo_bar("),
606+
"Expected the preserved class function to keep its Lua name.\n" + output);
607+
assertTrue(output.contains("Foo_bar1 = ({})"),
608+
"Expected the colliding class variable to be uniqued around the preserved function.\n" + output);
609+
}
610+
590611
@Test
591612
public void test_tempVarRemover() throws IOException {
592613
test().lines(

0 commit comments

Comments
 (0)