Skip to content

Commit f8f8a08

Browse files
committed
and some validation performance
1 parent ad92658 commit f8f8a08

7 files changed

Lines changed: 208 additions & 10 deletions

File tree

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/WurstChecker.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import de.peeeq.wurstscript.attributes.ErrorHandler;
77
import de.peeeq.wurstscript.attributes.names.DesugarArrayLength;
88
import de.peeeq.wurstscript.gui.WurstGui;
9+
import de.peeeq.wurstscript.validation.GlobalCaches;
910
import de.peeeq.wurstscript.validation.TRVEHelper;
1011
import de.peeeq.wurstscript.validation.WurstValidator;
1112

@@ -34,6 +35,7 @@ public void checkProg(WurstModel root, Collection<CompilationUnit> toCheck) {
3435
if (errorHandler.getErrorCount() > 0) return;
3536

3637
attachErrorHandler(root);
38+
clearGlobalCaches(root, toCheck);
3739

3840
expandModules(root);
3941

@@ -50,6 +52,14 @@ public void checkProg(WurstModel root, Collection<CompilationUnit> toCheck) {
5052
validator.validate(toCheck);
5153
}
5254

55+
private void clearGlobalCaches(WurstModel root, Collection<CompilationUnit> toCheck) {
56+
if (toCheck == root || toCheck.size() >= root.size()) {
57+
GlobalCaches.clearAll();
58+
} else {
59+
GlobalCaches.clearLookupCacheFor(toCheck);
60+
}
61+
}
62+
5363
private void attachErrorHandler(WurstModel root) {
5464
for (CompilationUnit cu : root) {
5565
cu.getCuInfo().setCuErrorHandler(errorHandler);

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/Exports.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package de.peeeq.wurstscript.attributes.names;
22

33

4+
import com.google.common.collect.ImmutableCollection;
45
import com.google.common.collect.ImmutableMultimap;
56
import com.google.common.collect.ImmutableMultimap.Builder;
7+
import com.google.common.collect.ImmutableSet;
68
import com.google.common.collect.Sets;
79
import de.peeeq.wurstscript.ast.WImport;
810
import de.peeeq.wurstscript.ast.WPackage;
@@ -47,12 +49,48 @@ private static void addExportedNameLinks(Builder<String, DefLink> result, WPacka
4749

4850
}
4951

52+
public static ImmutableCollection<DefLink> exportedNameLinks(WPackage p, String name) {
53+
ImmutableSet.Builder<DefLink> result = ImmutableSet.builder();
54+
addExportedNameLinks(result, p, name, Sets.newLinkedHashSet());
55+
return result.build();
56+
}
57+
58+
private static void addExportedNameLinks(ImmutableSet.Builder<DefLink> result, WPackage p, String name, Set<WPackage> alreadyImported) {
59+
if (alreadyImported.contains(p)) {
60+
return;
61+
}
62+
alreadyImported.add(p);
63+
64+
for (DefLink link : NameLinks.get(p.getElements(), name)) {
65+
if (link.getVisibility() == Visibility.LOCAL) {
66+
continue;
67+
}
68+
result.add(link.hidingPrivateAndProtected());
69+
}
70+
71+
for (WImport imp2 : p.getImports()) {
72+
if (imp2.getIsPublic()) {
73+
@Nullable
74+
WPackage imported = imp2.attrImportedPackage();
75+
if (imported != null) {
76+
addExportedNameLinks(result, imported, name, alreadyImported);
77+
}
78+
}
79+
}
80+
}
81+
5082
public static ImmutableMultimap<String, TypeLink> exportedTypeNameLinks(WPackage p) {
5183
Builder<String, TypeLink> result = ImmutableMultimap.builder();
5284
addExportedTypeNameLinks(result, p, Sets.newLinkedHashSet());
5385
return result.build();
5486
}
5587

88+
public static ImmutableCollection<TypeLink> exportedTypeNameLinks(WPackage p, String name) {
89+
ImmutableSet.Builder<TypeLink> result = ImmutableSet.builder();
90+
addExportedTypeNameLinks(result, p, name, Sets.newLinkedHashSet());
91+
return result.build();
92+
}
93+
5694

5795
private static void addExportedTypeNameLinks(Builder<String, TypeLink> result, WPackage p, Set<WPackage> alreadyImported) {
5896
if (alreadyImported.contains(p)) {
@@ -73,4 +111,27 @@ private static void addExportedTypeNameLinks(Builder<String, TypeLink> result, W
73111
}
74112

75113
}
114+
115+
private static void addExportedTypeNameLinks(ImmutableSet.Builder<TypeLink> result, WPackage p, String name, Set<WPackage> alreadyImported) {
116+
if (alreadyImported.contains(p)) {
117+
return;
118+
}
119+
alreadyImported.add(p);
120+
121+
for (TypeLink link : TypeNameLinks.get(p.getElements(), name)) {
122+
if (link.getVisibility() == Visibility.LOCAL) {
123+
continue;
124+
}
125+
result.add(link.hidingPrivateAndProtected());
126+
}
127+
128+
for (WImport imp2 : p.getImports()) {
129+
if (imp2.getIsPublic()) {
130+
WPackage imported = imp2.attrImportedPackage();
131+
if (imported != null) {
132+
addExportedTypeNameLinks(result, imported, name, alreadyImported);
133+
}
134+
}
135+
}
136+
}
76137
}

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameLinks.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package de.peeeq.wurstscript.attributes.names;
22

33
import com.google.common.collect.HashMultimap;
4+
import com.google.common.collect.ImmutableCollection;
45
import com.google.common.collect.ImmutableMultimap;
56
import com.google.common.collect.ImmutableMultimap.Builder;
7+
import com.google.common.collect.ImmutableList;
8+
import com.google.common.collect.ImmutableSet;
69
import com.google.common.collect.ImmutableSetMultimap;
710
import com.google.common.collect.Multimap;
811
import de.peeeq.wurstscript.WLogger;
@@ -268,6 +271,27 @@ public static ImmutableMultimap<String, DefLink> calculate(WPackage p) {
268271
return result.build();
269272
}
270273

274+
public static ImmutableCollection<DefLink> get(WPackage p, String name) {
275+
ImmutableSet.Builder<DefLink> result = ImmutableSet.builder();
276+
for (WImport imp : p.getImports()) {
277+
if (imp.getPackagename().equals("NoWurst")) {
278+
continue;
279+
}
280+
WPackage importedPackage = imp.attrImportedPackage();
281+
if (importedPackage == null) {
282+
WLogger.info("could not resolve import: " + Utils.printElementWithSource(Optional.of(imp)));
283+
continue;
284+
}
285+
if (p.getName().equals("WurstREPL")) {
286+
addHidingPrivate(result, importedPackage.getElements().attrNameLinks().get(name));
287+
result.addAll(get(importedPackage, name));
288+
} else {
289+
result.addAll(Exports.exportedNameLinks(importedPackage, name));
290+
}
291+
}
292+
return result.build();
293+
}
294+
271295

272296
public static ImmutableMultimap<String, DefLink> calculate(WEntities wEntities) {
273297
ImmutableMultimap.Builder<String, DefLink> result = ImmutableSetMultimap.builder();
@@ -290,6 +314,29 @@ public static ImmutableMultimap<String, DefLink> calculate(WEntities wEntities)
290314
return result.build();
291315
}
292316

317+
public static ImmutableCollection<DefLink> get(WEntities wEntities, String name) {
318+
ImmutableSet.Builder<DefLink> result = ImmutableSet.builder();
319+
for (WEntity e : wEntities) {
320+
if (e instanceof NameDef) {
321+
NameDef n = (NameDef) e;
322+
if (n.getName().equals(name)) {
323+
addNameDefDefLink(result::add, n, wEntities);
324+
}
325+
}
326+
if (e instanceof WScope && !(e instanceof ModuleDef)) {
327+
WScope scope = (WScope) e;
328+
List<TypeParamDef> typeParams;
329+
if (scope instanceof AstElementWithTypeParameters) {
330+
typeParams = ((AstElementWithTypeParameters) scope).getTypeParameters();
331+
} else {
332+
typeParams = Collections.emptyList();
333+
}
334+
addHidingPrivate(result, scope.attrNameLinks().get(name), typeParams);
335+
}
336+
}
337+
return result.build();
338+
}
339+
293340
public static ImmutableMultimap<String, DefLink> calculate(WurstModel model) {
294341
ImmutableMultimap.Builder<String, DefLink> result = ImmutableSetMultimap.builder();
295342
for (CompilationUnit cu : model) {
@@ -398,6 +445,24 @@ public static void addHidingPrivate(Builder<String, DefLink> result, Multimap<St
398445

399446
}
400447

448+
private static void addHidingPrivate(ImmutableSet.Builder<DefLink> result, Iterable<? extends DefLink> adding) {
449+
for (DefLink defLink : adding) {
450+
if (defLink.getVisibility() == Visibility.LOCAL) {
451+
continue;
452+
}
453+
result.add(defLink.hidingPrivate());
454+
}
455+
}
456+
457+
private static void addHidingPrivate(ImmutableSet.Builder<DefLink> result, Iterable<? extends DefLink> adding, List<TypeParamDef> typeParams) {
458+
for (DefLink defLink : adding) {
459+
if (defLink.getVisibility() == Visibility.LOCAL) {
460+
continue;
461+
}
462+
result.add(defLink.hidingPrivate().withGenericTypeParams(typeParams));
463+
}
464+
}
465+
401466
public static void addHidingPrivate(Multimap<String, DefLink> result, Multimap<String, DefLink> adding) {
402467
for (Entry<String, DefLink> e : adding.entries()) {
403468
if (e.getValue().getVisibility() == Visibility.LOCAL) {

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameResolution.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,22 @@ private static String memberFuncCacheName(String name, WurstType receiverType) {
2121
}
2222

2323
private static ImmutableCollection<DefLink> scopeNameLinks(WScope scope, String name) {
24+
if (scope instanceof WPackage) {
25+
return NameLinks.get((WPackage) scope, name);
26+
}
27+
if (scope instanceof WEntities) {
28+
return NameLinks.get((WEntities) scope, name);
29+
}
2430
return scope.attrNameLinks().get(name);
2531
}
2632

2733
private static ImmutableCollection<TypeLink> scopeTypeLinks(WScope scope, String name) {
34+
if (scope instanceof WPackage) {
35+
return TypeNameLinks.get((WPackage) scope, name);
36+
}
37+
if (scope instanceof WEntities) {
38+
return TypeNameLinks.get((WEntities) scope, name);
39+
}
2840
return scope.attrTypeNameLinks().get(name);
2941
}
3042

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/TypeNameLinks.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package de.peeeq.wurstscript.attributes.names;
22

3+
import com.google.common.collect.ImmutableCollection;
34
import com.google.common.collect.ImmutableMultimap;
5+
import com.google.common.collect.ImmutableSet;
46
import com.google.common.collect.ImmutableSetMultimap;
57
import de.peeeq.wurstscript.ast.*;
68

@@ -65,6 +67,18 @@ public static ImmutableMultimap<String, TypeLink> calculate(WPackage p) {
6567
return result.build();
6668
}
6769

70+
public static ImmutableCollection<TypeLink> get(WPackage p, String name) {
71+
ImmutableSet.Builder<TypeLink> result = ImmutableSet.builder();
72+
for (WImport imp : p.getImports()) {
73+
WPackage importedPackage = imp.attrImportedPackage();
74+
if (importedPackage == null) {
75+
continue;
76+
}
77+
result.addAll(Exports.exportedTypeNameLinks(importedPackage, name));
78+
}
79+
return result.build();
80+
}
81+
6882
public static ImmutableMultimap<String, TypeLink> calculate(WEntities wEntities) {
6983
ImmutableMultimap.Builder<String, TypeLink> result = ImmutableSetMultimap.builder();
7084
for (WEntity e : wEntities) {
@@ -76,6 +90,19 @@ public static ImmutableMultimap<String, TypeLink> calculate(WEntities wEntities)
7690
return result.build();
7791
}
7892

93+
public static ImmutableCollection<TypeLink> get(WEntities wEntities, String name) {
94+
ImmutableSet.Builder<TypeLink> result = ImmutableSet.builder();
95+
for (WEntity e : wEntities) {
96+
if (e instanceof TypeDef) {
97+
TypeDef n = (TypeDef) e;
98+
if (n.getName().equals(name)) {
99+
result.add(TypeLink.create(n, wEntities));
100+
}
101+
}
102+
}
103+
return result.build();
104+
}
105+
79106
public static ImmutableMultimap<String, TypeLink> calculate(WurstModel model) {
80107
ImmutableMultimap.Builder<String, TypeLink> result = ImmutableSetMultimap.builder();
81108
for (CompilationUnit cu : model) {

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@
66
import de.peeeq.wurstscript.intermediatelang.interpreter.LocalState;
77
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
88

9+
import java.util.ArrayDeque;
910
import java.util.Arrays;
11+
import java.util.Collection;
12+
import java.util.IdentityHashMap;
1013
import java.util.Map;
14+
import java.util.Set;
1115
import java.util.concurrent.atomic.AtomicLong;
1216

1317
// Expose static fields only if you already have them there; otherwise, just clear via dedicated methods.
@@ -146,6 +150,28 @@ public static void clearAll() {
146150
HasAnnotation.clearCaches();
147151
}
148152

153+
/**
154+
* Clears lookup entries whose query element belongs to one of the changed roots.
155+
* This keeps editor validation from throwing away hot lookup data for unchanged files.
156+
*/
157+
public static void clearLookupCacheFor(Collection<? extends Element> roots) {
158+
if (roots.isEmpty()) {
159+
return;
160+
}
161+
Set<Element> affected = java.util.Collections.newSetFromMap(new IdentityHashMap<>());
162+
ArrayDeque<Element> todo = new ArrayDeque<>(roots);
163+
while (!todo.isEmpty()) {
164+
Element e = todo.removeLast();
165+
if (!affected.add(e)) {
166+
continue;
167+
}
168+
for (int i = 0; i < e.size(); i++) {
169+
todo.add(e.get(i));
170+
}
171+
}
172+
lookupCache.keySet().removeIf(key -> affected.contains(key.element));
173+
}
174+
149175
public enum LookupType {
150176
FUNC, VAR, TYPE, PACKAGE, MEMBER_FUNC, MEMBER_VAR
151177
}

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

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,10 @@ public WurstValidator(WurstModel root) {
6464

6565
public void validate(Collection<CompilationUnit> toCheck) {
6666
try {
67-
functionCount = countFunctions();
67+
functionCount = countFunctions(toCheck);
6868
visitedFunctions = 0;
6969
heavyFunctions.clear();
7070
heavyBlocks.clear();
71-
GlobalCaches.clearAll();
7271

7372
lightValidation(toCheck);
7473

@@ -123,11 +122,6 @@ private void lightValidation(Collection<CompilationUnit> toCheck) {
123122
for (CompilationUnit cu : toCheck) {
124123
walkTree(cu);
125124
}
126-
127-
// Build CFG once for heavy phase (enables reachability/prev/next attrs)
128-
for (CompilationUnit cu : toCheck) {
129-
computeFlowAttributes(cu);
130-
}
131125
}
132126

133127
/** Visit only statements under root and run checkReachability where applicable. */
@@ -1174,16 +1168,19 @@ private void checkIntVal(ExprIntVal e) {
11741168
// check range? ...
11751169
}
11761170

1177-
private int countFunctions() {
1171+
private int countFunctions(Collection<CompilationUnit> toCheck) {
11781172
final int[] functionCount = new int[1];
1179-
prog.accept(new WurstModel.DefaultVisitor() {
1173+
Element.DefaultVisitor visitor = new Element.DefaultVisitor() {
11801174

11811175
@Override
11821176
public void visit(FuncDef f) {
11831177
super.visit(f);
11841178
functionCount[0]++;
11851179
}
1186-
});
1180+
};
1181+
for (CompilationUnit cu : toCheck) {
1182+
cu.accept(visitor);
1183+
}
11871184
return functionCount[0];
11881185
}
11891186

0 commit comments

Comments
 (0)