Skip to content

Commit ad92658

Browse files
committed
simply override objmods if redefined in code
1 parent 1ec8b58 commit ad92658

3 files changed

Lines changed: 91 additions & 2 deletions

File tree

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/intermediateLang/interpreter/CompiletimeNatives.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ public ILconstTuple createObjectDefinition(ILconstString fileType, ILconstInt ne
4141
String objIdString = ObjectHelper.objectIdIntToString(newUnitId.getVal());
4242
boolean isMeleeOverride = newUnitId.getVal() == deriveFrom.getVal();
4343

44-
if (!isMeleeOverride && dataStore.getObjs().containsKey(ObjId.valueOf(objIdString))) {
45-
globalState.compilationError("Object definition with id " + objIdString + " already exists.");
44+
if (!globalState.registerCreatedObjectDefinition(fileType.getVal(), objIdString)) {
45+
globalState.compilationError("Object definition with id " + objIdString + " is defined more than once.");
4646
}
4747
ObjMod.Obj objDef = newDefFromFiletype(dataStore, deriveFrom.getVal(), newUnitId.getVal(), isMeleeOverride);
4848
if (!isMeleeOverride) {
@@ -59,10 +59,12 @@ private ObjMod.Obj newDefFromFiletype(ObjMod<? extends ObjMod.Obj> dataStore, in
5959
if (isMeleeOverride) {
6060
ObjId id = ObjId.valueOf(ObjectHelper.objectIdIntToString(newId));
6161
// same id => modify melee/original definition table
62+
dataStore.removeObj(id);
6263
return dataStore.addObj(id, null);
6364
}
6465
ObjId baseIdS = ObjId.valueOf(ObjectHelper.objectIdIntToString(base));
6566
ObjId newIdS = ObjId.valueOf(ObjectHelper.objectIdIntToString(newId));
67+
dataStore.removeObj(newIdS);
6668
return dataStore.addObj(newIdS, baseIdS);
6769
}
6870

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/intermediateLang/interpreter/ProgramStateIO.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public class ProgramStateIO extends ProgramState {
3636
private @Nullable final MpqEditor mpqEditor;
3737
private final Map<ObjectFileType, ObjMod<? extends ObjMod.Obj>> dataStoreMap = Maps.newLinkedHashMap();
3838
private final Map<ObjectFileType, String> dataStoreHashes = Maps.newLinkedHashMap();
39+
private final Map<String, Set<String>> createdObjectDefinitionIds = Maps.newLinkedHashMap();
3940
private int id = 0;
4041
private final Map<String, ObjMod.Obj> objDefinitions = Maps.newLinkedHashMap();
4142
private PrintStream outStream = System.err;
@@ -368,6 +369,11 @@ ObjMod.Obj getObjectDefinition(String key) {
368369
return objDefinitions.get(key);
369370
}
370371

372+
boolean registerCreatedObjectDefinition(String fileExtension, String objId) {
373+
Set<String> ids = createdObjectDefinitionIds.computeIfAbsent(fileExtension, k -> new LinkedHashSet<>());
374+
return ids.add(objId);
375+
}
376+
371377
/**
372378
* Calculate hash of an object file's contents
373379
*/

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

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,34 @@
11
package tests.wurstscript.tests;
22

33
import de.peeeq.wurstio.intermediateLang.interpreter.CompiletimeNatives;
4+
import de.peeeq.wurstio.intermediateLang.interpreter.ProgramStateIO;
45
import de.peeeq.wurstio.objectreader.ObjectHelper;
6+
import de.peeeq.wurstscript.ast.Ast;
7+
import de.peeeq.wurstscript.ast.Element;
8+
import de.peeeq.wurstscript.gui.WurstGuiLogger;
9+
import de.peeeq.wurstscript.intermediatelang.ILconstInt;
510
import de.peeeq.wurstscript.intermediatelang.ILconstString;
11+
import de.peeeq.wurstscript.jassIm.ImProg;
12+
import de.peeeq.wurstscript.jassIm.JassIm;
613
import net.moonlightflower.wc3libs.bin.ObjMod;
714
import net.moonlightflower.wc3libs.bin.app.objMod.W3A;
815
import net.moonlightflower.wc3libs.bin.app.objMod.W3U;
916
import net.moonlightflower.wc3libs.dataTypes.DataType;
17+
import net.moonlightflower.wc3libs.dataTypes.app.War3String;
1018
import net.moonlightflower.wc3libs.dataTypes.app.War3Real;
1119
import net.moonlightflower.wc3libs.misc.MetaFieldId;
1220
import net.moonlightflower.wc3libs.misc.ObjId;
1321
import org.testng.annotations.Test;
1422

1523
import java.lang.reflect.Method;
24+
import java.util.HashMap;
1625
import java.util.List;
26+
import java.util.Optional;
1727
import java.util.Set;
1828
import java.util.stream.Collectors;
1929

2030
import static org.testng.Assert.assertEquals;
31+
import static org.testng.Assert.assertFalse;
2132
import static org.testng.Assert.assertTrue;
2233

2334
public class CompiletimeNativesTest {
@@ -104,4 +115,74 @@ public void differentIdsObjectDefinitionUsesCustomTable() throws Exception {
104115
assertEquals(w3u.getOrigObjs().size(), 0);
105116
assertEquals(w3u.getCustomObjs().size(), 1);
106117
}
118+
119+
@Test
120+
public void differentIdsObjectDefinitionOverwritesExistingMapObject() throws Exception {
121+
CompiletimeNatives natives = new CompiletimeNatives(null, null, false);
122+
W3U w3u = new W3U();
123+
int hfoo = ObjectHelper.objectIdStringToInt("hfoo");
124+
int hf01 = ObjectHelper.objectIdStringToInt("hf01");
125+
W3U.Obj existing = w3u.addObj(ObjId.valueOf("hf01"), ObjId.valueOf("hpea"));
126+
existing.addMod(new ObjMod.Obj.Mod(MetaFieldId.valueOf("unam"), ObjMod.ValType.STRING, War3String.valueOf("old map object")));
127+
128+
Method newDefFromFiletype = CompiletimeNatives.class.getDeclaredMethod(
129+
"newDefFromFiletype",
130+
ObjMod.class,
131+
int.class,
132+
int.class,
133+
boolean.class
134+
);
135+
newDefFromFiletype.setAccessible(true);
136+
137+
ObjMod.Obj obj = (ObjMod.Obj) newDefFromFiletype.invoke(natives, w3u, hfoo, hf01, false);
138+
139+
assertEquals(w3u.getCustomObjs().size(), 1, "Existing map object should be replaced instead of duplicated");
140+
assertEquals(obj.getId().getVal(), "hf01");
141+
assertEquals(obj.getBaseId().getVal(), "hfoo");
142+
assertEquals(obj.getMods().size(), 0, "Overwritten map object mods should not leak into the Wurst-created object");
143+
}
144+
145+
@Test
146+
public void duplicateCodeObjectDefinitionsReportError() {
147+
WurstGuiLogger gui = new WurstGuiLogger();
148+
ProgramStateIO state = new ProgramStateIO(Optional.empty(), null, gui, emptyProg(), true);
149+
CompiletimeNatives natives = new CompiletimeNatives(state, null, false);
150+
int hfoo = ObjectHelper.objectIdStringToInt("hfoo");
151+
int hf01 = ObjectHelper.objectIdStringToInt("hf01");
152+
153+
natives.createObjectDefinition(new ILconstString("w3u"), new ILconstInt(hf01), new ILconstInt(hfoo));
154+
natives.createObjectDefinition(new ILconstString("w3u"), new ILconstInt(hf01), new ILconstInt(hfoo));
155+
156+
assertEquals(gui.getErrorCount(), 1);
157+
assertTrue(gui.getErrors().contains("Object definition with id hf01 is defined more than once."));
158+
}
159+
160+
@Test
161+
public void createObjectDefinitionDoesNotReportExistingMapObjectAsError() throws Exception {
162+
WurstGuiLogger gui = new WurstGuiLogger();
163+
ProgramStateIO state = new ProgramStateIO(Optional.empty(), null, gui, emptyProg(), true);
164+
CompiletimeNatives natives = new CompiletimeNatives(state, null, false);
165+
int hfoo = ObjectHelper.objectIdStringToInt("hfoo");
166+
int hf01 = ObjectHelper.objectIdStringToInt("hf01");
167+
168+
Method getDataStore = ProgramStateIO.class.getDeclaredMethod("getDataStore", String.class);
169+
getDataStore.setAccessible(true);
170+
W3U w3u = (W3U) getDataStore.invoke(state, "w3u");
171+
W3U.Obj existing = w3u.addObj(ObjId.valueOf("hf01"), ObjId.valueOf("hpea"));
172+
existing.addMod(new ObjMod.Obj.Mod(MetaFieldId.valueOf("unam"), ObjMod.ValType.STRING, War3String.valueOf("old map object")));
173+
174+
natives.createObjectDefinition(new ILconstString("w3u"), new ILconstInt(hf01), new ILconstInt(hfoo));
175+
176+
assertEquals(gui.getErrorCount(), 0);
177+
assertEquals(w3u.getCustomObjs().size(), 1);
178+
ObjMod.Obj obj = w3u.getCustomObjs().get(0);
179+
assertEquals(obj.getId().getVal(), "hf01");
180+
assertEquals(obj.getBaseId().getVal(), "hfoo");
181+
assertFalse(obj.getMods().stream().anyMatch(m -> m.getId().getVal().equals("unam")));
182+
}
183+
184+
private ImProg emptyProg() {
185+
Element trace = Ast.NoExpr();
186+
return JassIm.ImProg(trace, JassIm.ImVars(), JassIm.ImFunctions(), JassIm.ImMethods(), JassIm.ImClasses(), JassIm.ImTypeClassFuncs(), new HashMap<>());
187+
}
107188
}

0 commit comments

Comments
 (0)