Skip to content

Commit a32626d

Browse files
committed
better model robustness
1 parent dd91877 commit a32626d

5 files changed

Lines changed: 245 additions & 36 deletions

File tree

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ModelManagerImpl.java

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,25 +87,30 @@ private List<CompilationUnit> getJassdocCUs(Path jassdoc, WurstGui gui) {
8787

8888
@Override
8989
public Changes removeCompilationUnit(WFile resource) {
90-
parseErrors.remove(resource);
9190
WurstModel model2 = model;
92-
if (model2 == null) {
93-
return Changes.empty();
94-
}
95-
96-
syncCompilationUnitContent(resource, "");
9791
List<CompilationUnit> toRemove = new ArrayList<>();
98-
for (CompilationUnit compilationUnit : model2) {
99-
if (wFile(compilationUnit).equals(resource)) {
100-
toRemove.add(compilationUnit);
92+
if (model2 != null) {
93+
for (CompilationUnit compilationUnit : model2) {
94+
if (wFile(compilationUnit).equals(resource)) {
95+
toRemove.add(compilationUnit);
96+
}
10197
}
98+
model2.removeAll(toRemove);
10299
}
103-
model2.removeAll(toRemove);
104-
return new Changes(toRemove.stream()
105-
.map(this::wFile),
100+
101+
// Always clear state and diagnostics for removed files.
102+
clearFileState(resource);
103+
reportErrors("remove cu ", resource, Collections.emptyList());
104+
105+
toRemove.forEach(compilationunitFile::remove);
106+
107+
return new Changes(
108+
java.util.Collections.singletonList(resource),
106109
toRemove.stream()
107110
.flatMap(cu -> cu.getPackages().stream())
108-
.map(WPackage::getName));
111+
.map(WPackage::getName)
112+
.collect(Collectors.toList())
113+
);
109114
}
110115

111116
@Override
@@ -526,9 +531,14 @@ private CompilationUnit replaceCompilationUnit(WFile filename, String contents,
526531
if (fileHashcodes.containsKey(filename)) {
527532
int oldHash = fileHashcodes.get(filename);
528533
if (oldHash == contents.hashCode()) {
529-
// no change
530-
WLogger.trace("CU " + filename + " was unchanged.");
531-
return getCompilationUnit(filename);
534+
CompilationUnit existing = getCompilationUnit(filename);
535+
if (existing != null) {
536+
// no change
537+
WLogger.trace("CU " + filename + " was unchanged.");
538+
return existing;
539+
}
540+
// Stale hash cache after remove/move; CU is gone, so reparse.
541+
WLogger.info("CU hash unchanged but model entry missing for " + filename + ", reparsing.");
532542
} else {
533543
WLogger.info("CU changed. oldHash = " + oldHash + " == " + contents.hashCode());
534544
}
@@ -557,6 +567,12 @@ private CompilationUnit replaceCompilationUnit(WFile filename, String contents,
557567
return cu;
558568
}
559569

570+
private void clearFileState(WFile file) {
571+
parseErrors.remove(file);
572+
otherErrors.remove(file);
573+
fileHashcodes.remove(file);
574+
}
575+
560576
@Override
561577
public CompilationUnit getCompilationUnit(WFile filename) {
562578
List<CompilationUnit> matches = getCompilationUnits(Collections.singletonList(filename));

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/CodeActionRequest.java

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@
2222
import org.eclipse.lsp4j.TextDocumentIdentifier;
2323
import org.eclipse.lsp4j.jsonrpc.messages.Either;
2424

25+
import java.io.File;
2526
import java.util.ArrayList;
27+
import java.util.Collection;
2628
import java.util.Collections;
29+
import java.util.LinkedHashSet;
2730
import java.util.List;
2831
import java.util.Optional;
32+
import java.util.Set;
2933
import java.util.stream.Collectors;
3034

3135
import static de.peeeq.wurstio.languageserver.WurstCommands.WURST_PERFORM_CODE_ACTION;
@@ -113,7 +117,7 @@ public List<Either<Command, CodeAction>> execute(ModelManager modelManager) {
113117
private List<Either<Command, CodeAction>> handleMissingName(ModelManager modelManager, NameRef nr) {
114118
String funcName = nr.getVarName();
115119
WurstModel model = modelManager.getModel();
116-
List<String> possibleImports = new ArrayList<>();
120+
Set<String> possibleImports = new LinkedHashSet<>();
117121
WurstType receiverType = null;
118122
if (nr instanceof ExprMember) {
119123
ExprMember m = (ExprMember) nr;
@@ -136,6 +140,7 @@ private List<Either<Command, CodeAction>> handleMissingName(ModelManager modelMa
136140
}
137141
}
138142
}
143+
addDependencyPackageFallback(modelManager, possibleImports, funcName);
139144

140145
return makeImportCommands(possibleImports);
141146

@@ -157,7 +162,7 @@ private List<Either<Command, CodeAction>> handleMissingFunction(ModelManager mod
157162
receiverType = m.getLeft().attrTyp();
158163
}
159164
WurstModel model = modelManager.getModel();
160-
List<String> possibleImports = new ArrayList<>();
165+
Set<String> possibleImports = new LinkedHashSet<>();
161166
for (CompilationUnit cu : model) {
162167
withNextPackage:
163168
for (WPackage wPackage : cu.getPackages()) {
@@ -171,6 +176,7 @@ private List<Either<Command, CodeAction>> handleMissingFunction(ModelManager mod
171176
}
172177
}
173178
}
179+
addDependencyPackageFallback(modelManager, possibleImports, funcName);
174180

175181
return Utils.concatLists(makeImportCommands(possibleImports), makeCreateFunctionQuickfix(fr));
176182
}
@@ -342,14 +348,15 @@ public void indent(StringBuilder sb) {
342348

343349
private List<Either<Command, CodeAction>> handleMissingType(ModelManager modelManager, String typeName) {
344350
WurstModel model = modelManager.getModel();
345-
List<String> possibleImports = new ArrayList<>();
351+
Set<String> possibleImports = new LinkedHashSet<>();
346352
for (CompilationUnit cu : model) {
347353
for (WPackage wPackage : cu.getPackages()) {
348354
if (!wPackage.attrExportedTypeNameLinks().get(typeName).isEmpty()) {
349355
possibleImports.add(wPackage.getName());
350356
}
351357
}
352358
}
359+
addDependencyPackageFallback(modelManager, possibleImports, typeName);
353360

354361
return makeImportCommands(possibleImports);
355362
}
@@ -361,7 +368,7 @@ private List<Either<Command, CodeAction>> handleMissingClass(ModelManager modelM
361368
// that are not yet imported into the project.
362369

363370
WurstModel model = modelManager.getModel();
364-
List<String> possibleImports = new ArrayList<>();
371+
Set<String> possibleImports = new LinkedHashSet<>();
365372
for (CompilationUnit cu : model) {
366373
withNextPackage:
367374
for (WPackage wPackage : cu.getPackages()) {
@@ -373,14 +380,15 @@ private List<Either<Command, CodeAction>> handleMissingClass(ModelManager modelM
373380
}
374381
}
375382
}
383+
addDependencyPackageFallback(modelManager, possibleImports, typeName);
376384

377385
return makeImportCommands(possibleImports);
378386
}
379387

380388
private List<Either<Command, CodeAction>> handleMissingModule(ModelManager modelManager, String moduleName) {
381389

382390
WurstModel model = modelManager.getModel();
383-
List<String> possibleImports = new ArrayList<>();
391+
Set<String> possibleImports = new LinkedHashSet<>();
384392
for (CompilationUnit cu : model) {
385393
withNextPackage:
386394
for (WPackage wPackage : cu.getPackages()) {
@@ -392,13 +400,23 @@ private List<Either<Command, CodeAction>> handleMissingModule(ModelManager model
392400
}
393401
}
394402
}
403+
addDependencyPackageFallback(modelManager, possibleImports, moduleName);
395404

396405
return makeImportCommands(possibleImports);
397406
}
398407

399408

400409

401-
private List<Either<Command, CodeAction>> makeImportCommands(List<String> possibleImports) {
410+
private void addDependencyPackageFallback(ModelManager modelManager, Set<String> possibleImports, String unresolvedName) {
411+
for (File dep : modelManager.getDependencyWurstFiles()) {
412+
String libName = Utils.getLibName(dep);
413+
if (libName.equals(unresolvedName)) {
414+
possibleImports.add(libName);
415+
}
416+
}
417+
}
418+
419+
private List<Either<Command, CodeAction>> makeImportCommands(Collection<String> possibleImports) {
402420
return possibleImports.stream()
403421
.map(this::makeImportCommand)
404422
.collect(Collectors.toList());

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/MapRequest.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -244,21 +244,36 @@ protected File runJassHotCodeReload(File mapScript) throws IOException, Interrup
244244
private void purgeUnimportedFiles(WurstModel model) {
245245

246246
Set<CompilationUnit> imported = model.stream()
247-
.filter(cu -> isInWurstFolder(cu.getCuInfo().getFile()) || cu.getCuInfo().getFile().endsWith(".j")).collect(Collectors.toSet());
247+
.filter(cu -> isInProjectWurstFolder(cu.getCuInfo().getFile()) || isProjectWar3MapScript(cu.getCuInfo().getFile()))
248+
.collect(Collectors.toSet());
248249
addImports(imported, imported);
249250

250251
model.removeIf(cu -> !imported.contains(cu));
251252
}
252253

253-
private boolean isInWurstFolder(String file) {
254-
Path p = Paths.get(file);
255-
Path w;
254+
private boolean isProjectWar3MapScript(String file) {
255+
if (!file.endsWith("war3map.j")) {
256+
return false;
257+
}
258+
Path p = Paths.get(file).toAbsolutePath().normalize();
259+
Path projectWurstFolder;
260+
try {
261+
projectWurstFolder = workspaceRoot.getPath().resolve("wurst").toAbsolutePath().normalize();
262+
} catch (FileNotFoundException e) {
263+
return false;
264+
}
265+
return p.startsWith(projectWurstFolder) && java.nio.file.Files.exists(p);
266+
}
267+
268+
private boolean isInProjectWurstFolder(String file) {
269+
Path p = Paths.get(file).toAbsolutePath().normalize();
270+
Path projectWurstFolder;
256271
try {
257-
w = workspaceRoot.getPath();
272+
projectWurstFolder = workspaceRoot.getPath().resolve("wurst").toAbsolutePath().normalize();
258273
} catch (FileNotFoundException e) {
259274
return false;
260275
}
261-
return p.startsWith(w)
276+
return p.startsWith(projectWurstFolder)
262277
&& java.nio.file.Files.exists(p)
263278
&& Utils.isWurstFile(file);
264279
}

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrImportedPackage.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@ public static ImmutableMap<String, WPackage> getPackages(WurstModel wurstModel)
4242
WPackage old = result.put(p.getName(), p);
4343
if (old != null) {
4444
if (!p.getName().equals("Wurst")) {
45-
// TODO should this really error?
46-
p.addError("Package " + p.getName() + " is already defined in " + Utils.printPos(old.getSource()));
47-
old.addError("Package " + p.getName() + " is already defined in " + Utils.printPos(p.getSource()));
45+
p.addError("Package '" + p.getName() + "' is defined multiple times. "
46+
+ "This is currently not supported. First definition: " + Utils.printPos(old.getSource()));
4847
}
4948
}
5049
}

0 commit comments

Comments
 (0)