11package de .peeeq .wurstscript .attributes .names ;
22
33import com .google .common .collect .HashMultimap ;
4- import com .google .common .collect .ImmutableCollection ;
5- import com .google .common .collect .ImmutableList ;
64import com .google .common .collect .ImmutableMultimap ;
5+ import com .google .common .collect .ImmutableMultimap .Builder ;
76import com .google .common .collect .ImmutableSetMultimap ;
87import com .google .common .collect .Multimap ;
98import de .peeeq .wurstscript .WLogger ;
2120
2221public class NameLinks {
2322
24- // OPTIMIZATION 1: Cache for package name links to avoid recomputation
25- private static final Map <WPackage , ImmutableMultimap <String , DefLink >> packageNameLinksCache =
26- new WeakHashMap <>();
27-
2823 static private class OverrideCheckResult {
24+ // does this override some other function
2925 boolean doesOverride = false ;
26+
27+ // overrides a function from a class or module
28+ // (for interfaces override modifier is optional)
3029 boolean requiresOverrideMod = false ;
30+
31+ // errors for functions with same name that it does not override
3132 io .vavr .collection .List <String > overrideErrors = io .vavr .collection .List .empty ();
3233
3334 public void addError (String error ) {
@@ -65,6 +66,7 @@ private static Map<String, Map<FuncLink, OverrideCheckResult>> initOverrideMap(M
6566 }
6667
6768 private static void reportOverrideErrors (Map <String , Map <FuncLink , OverrideCheckResult >> overrideCheckResults ) {
69+ // report override errors
6870 for (Map <FuncLink , OverrideCheckResult > map : overrideCheckResults .values ()) {
6971 for (Entry <FuncLink , OverrideCheckResult > e : map .entrySet ()) {
7072 FunctionDefinition f = e .getKey ().getDef ();
@@ -83,6 +85,7 @@ private static void reportOverrideErrors(Map<String, Map<FuncLink, OverrideCheck
8385 f .addWarning ("Function " + f .getName () + " should be marked with the 'override' modifier." );
8486 }
8587 }
88+
8689 }
8790 }
8891 }
@@ -102,6 +105,7 @@ private static void addNamesFromExtendedInterfaces(Multimap<String, DefLink> res
102105 }
103106 }
104107
108+
105109 private static void addNamesFromImplementedInterfaces (Multimap <String , DefLink > result , WurstTypeClass classDef , Map <String , Map <FuncLink , OverrideCheckResult >> overrideCheckResults ) {
106110 for (WurstTypeInterface interfaceType : classDef .implementedInterfaces ()) {
107111 addNewNameLinks (result , overrideCheckResults , interfaceType .nameLinks (), false );
@@ -126,6 +130,7 @@ private static void addNewNameLinks(Multimap<String, DefLink> result, Map<String
126130 if (def instanceof FuncLink ) {
127131 FuncLink func = (FuncLink ) def ;
128132
133+ // check if function is overridden by any other function in
129134 Map <FuncLink , OverrideCheckResult > otherFuncs = overrideCheckResults .getOrDefault (name , Collections .emptyMap ());
130135 for (Entry <FuncLink , OverrideCheckResult > e2 : otherFuncs .entrySet ()) {
131136 FuncLink otherFunc = e2 .getKey ();
@@ -141,14 +146,18 @@ private static void addNewNameLinks(Multimap<String, DefLink> result, Map<String
141146 } else {
142147 checkResult .addError (error );
143148 }
149+
150+
144151 }
152+
145153 }
146154 if (!isOverridden ) {
147155 result .put (name , def .hidingPrivate ());
148156 }
149157 }
150158 }
151159
160+
152161 public static ImmutableMultimap <String , DefLink > calculate (CompilationUnit cu ) {
153162 ImmutableMultimap .Builder <String , DefLink > result = ImmutableSetMultimap .builder ();
154163 addJassNames (result , cu );
@@ -164,7 +173,8 @@ public static ImmutableMultimap<String, DefLink> calculate(AstElementWithBody c)
164173 return result .build ();
165174 }
166175
167- private static void addVarDefIfAny (ImmutableMultimap .Builder <String , DefLink > result , WScope s ) {
176+
177+ private static void addVarDefIfAny (Builder <String , DefLink > result , WScope s ) {
168178 if (s instanceof LoopStatementWithVarDef ) {
169179 LoopStatementWithVarDef l = (LoopStatementWithVarDef ) s ;
170180 result .put (l .getLoopVar ().getName (), VarLink .create (l .getLoopVar (), s ));
@@ -177,8 +187,10 @@ public static ImmutableMultimap<String, DefLink> calculate(EnumDef e) {
177187 return result .build ();
178188 }
179189
190+
180191 public static ImmutableMultimap <String , DefLink > calculate (@ SuppressWarnings ("unused" ) NativeFunc nativeFunc ) {
181- return ImmutableMultimap .of ();
192+ ImmutableMultimap .Builder <String , DefLink > result = ImmutableSetMultimap .builder ();
193+ return result .build ();
182194 }
183195
184196 public static ImmutableMultimap <String , DefLink > calculate (TupleDef t ) {
@@ -188,19 +200,7 @@ public static ImmutableMultimap<String, DefLink> calculate(TupleDef t) {
188200 }
189201
190202 public static ImmutableMultimap <String , DefLink > calculate (WPackage p ) {
191- // OPTIMIZATION 2: Check cache first
192- ImmutableMultimap <String , DefLink > cached = packageNameLinksCache .get (p );
193- if (cached != null ) {
194- return cached ;
195- }
196-
197- // OPTIMIZATION 3: Estimate size based on imports
198- int estimatedSize = p .getImports ().size () * 50 ; // rough estimate
199- ImmutableMultimap .Builder <String , DefLink > result =
200- new ImmutableMultimap .Builder <>();
201-
202- // OPTIMIZATION 4: Collect all imported packages first
203- List <WPackage > importedPackages = new ArrayList <>(p .getImports ().size ());
203+ ImmutableMultimap .Builder <String , DefLink > result = ImmutableSetMultimap .builder ();
204204 for (WImport imp : p .getImports ()) {
205205 if (imp .getPackagename ().equals ("NoWurst" )) {
206206 continue ;
@@ -210,53 +210,20 @@ public static ImmutableMultimap<String, DefLink> calculate(WPackage p) {
210210 WLogger .info ("could not resolve import: " + Utils .printElementWithSource (Optional .of (imp )));
211211 continue ;
212212 }
213- importedPackages .add (importedPackage );
214- }
215-
216- // OPTIMIZATION 5: Special handling for REPL (all names)
217- if (p .getName ().equals ("WurstREPL" )) {
218- for (WPackage importedPackage : importedPackages ) {
213+ if (p .getName ().equals ("WurstREPL" )) {
214+ // the REPL is special and can use all names
219215 result .putAll (importedPackage .getElements ().attrNameLinks ());
220216 result .putAll (importedPackage .attrNameLinks ());
221- }
222- } else {
223- // OPTIMIZATION 6: Batch process exported names
224- // Instead of calling putAll for each package, collect into intermediate structure
225- if (importedPackages .size () == 1 ) {
226- // Fast path for single import
227- result .putAll (importedPackages .get (0 ).attrExportedNameLinks ());
228- } else if (!importedPackages .isEmpty ()) {
229- // OPTIMIZATION 7: Use a Set to track already added names (for deduplication)
230- Map <String , Set <DefLink >> mergedLinks = new HashMap <>(estimatedSize );
231-
232- for (WPackage importedPackage : importedPackages ) {
233- ImmutableMultimap <String , DefLink > exportedLinks = importedPackage .attrExportedNameLinks ();
234-
235- // OPTIMIZATION 8: Iterate entries once and merge
236- for (Map .Entry <String , DefLink > entry : exportedLinks .entries ()) {
237- String name = entry .getKey ();
238- DefLink link = entry .getValue ();
239-
240- mergedLinks .computeIfAbsent (name , k -> new LinkedHashSet <>(4 ))
241- .add (link );
242- }
243- }
244-
245- // OPTIMIZATION 9: Bulk add to result
246- for (Map .Entry <String , Set <DefLink >> entry : mergedLinks .entrySet ()) {
247- result .putAll (entry .getKey (), entry .getValue ());
248- }
217+ } else {
218+ // normal packages can only use the exported names of a package
219+ result .putAll (importedPackage .attrExportedNameLinks ());
249220 }
250221 }
251222
252- ImmutableMultimap <String , DefLink > finalResult = result .build ();
253-
254- // OPTIMIZATION 10: Cache the result
255- packageNameLinksCache .put (p , finalResult );
256-
257- return finalResult ;
223+ return result .build ();
258224 }
259225
226+
260227 public static ImmutableMultimap <String , DefLink > calculate (WEntities wEntities ) {
261228 ImmutableMultimap .Builder <String , DefLink > result = ImmutableSetMultimap .builder ();
262229 for (WEntity e : wEntities ) {
@@ -297,22 +264,23 @@ public static ImmutableMultimap<String, DefLink> calculate(WStatements statement
297264 return result .build ();
298265 }
299266
300- private static void addParametersIfAny (ImmutableMultimap . Builder <String , DefLink > result , WScope s ) {
267+ private static void addParametersIfAny (Builder <String , DefLink > result , WScope s ) {
301268 if (s instanceof AstElementWithParameters ) {
302269 AstElementWithParameters withParams = (AstElementWithParameters ) s ;
303270 for (WParameter p : withParams .getParameters ()) {
304271 result .put (p .getName (), VarLink .create (p , s ));
305272 }
306273 }
274+
307275 }
308276
309- private static void addPackages (ImmutableMultimap . Builder <String , DefLink > result , CompilationUnit cu ) {
277+ private static void addPackages (Builder <String , DefLink > result , CompilationUnit cu ) {
310278 for (WPackage p : cu .getPackages ()) {
311279 result .put (p .getName (), PackageLink .create (p , cu ));
312280 }
313281 }
314282
315- private static void addJassNames (ImmutableMultimap . Builder <String , DefLink > result , CompilationUnit cu ) {
283+ private static void addJassNames (Builder <String , DefLink > result , CompilationUnit cu ) {
316284 for (JassToplevelDeclaration jd : cu .getJassDecls ()) {
317285 if (jd instanceof NameDef ) {
318286 NameDef def = (NameDef ) jd ;
@@ -324,6 +292,7 @@ private static void addJassNames(ImmutableMultimap.Builder<String, DefLink> resu
324292 }
325293 }
326294
295+
327296 private static void addNameDefDefLink (Consumer <DefLink > result , NameDef def , WScope scope ) {
328297 if (def instanceof VarDef ) {
329298 result .accept (VarLink .create (((VarDef ) def ), scope ));
@@ -338,14 +307,15 @@ private static void addNameDefDefLink(Consumer<DefLink> result, NameDef def, WSc
338307 }
339308 }
340309
341- private static void addNameDefDefLink (ImmutableMultimap . Builder <String , DefLink > result , NameDef def , WScope scope ) {
310+ private static void addNameDefDefLink (Builder <String , DefLink > result , NameDef def , WScope scope ) {
342311 addNameDefDefLink (l -> result .put (l .getName (), l ), def , scope );
343312 }
344313
345314 private static void addNameDefDefLink (Multimap <String , DefLink > result , NameDef def , WScope scope ) {
346315 addNameDefDefLink (l -> result .put (l .getName (), l ), def , scope );
347316 }
348317
318+
349319 private static void addNamesFromUsedModuleInstantiations (ClassOrModuleOrModuleInstanciation c ,
350320 Multimap <String , DefLink > result , Map <String , Map <FuncLink , OverrideCheckResult >> overrideCheckResults ) {
351321 for (ModuleInstanciation m : c .getModuleInstanciations ()) {
@@ -360,7 +330,7 @@ private static void addDefinedNames(Multimap<String, DefLink> result, ClassOrMod
360330 addDefinedNames (result , c , c .getInnerClasses ());
361331 }
362332
363- private static void addDefinedNames (ImmutableMultimap . Builder <String , DefLink > result , WScope definedIn , List <? extends NameDef > slots ) {
333+ private static void addDefinedNames (Builder <String , DefLink > result , WScope definedIn , List <? extends NameDef > slots ) {
364334 for (NameDef n : slots ) {
365335 addNameDefDefLink (result , n , definedIn );
366336 }
@@ -372,13 +342,15 @@ private static void addDefinedNames(Multimap<String, DefLink> result, WScope def
372342 }
373343 }
374344
375- public static void addHidingPrivate (ImmutableMultimap .Builder <String , DefLink > result , Multimap <String , DefLink > adding , List <TypeParamDef > typeParams ) {
345+
346+ public static void addHidingPrivate (Builder <String , DefLink > result , Multimap <String , DefLink > adding , List <TypeParamDef > typeParams ) {
376347 for (Entry <String , DefLink > e : adding .entries ()) {
377348 if (e .getValue ().getVisibility () == Visibility .LOCAL ) {
378349 continue ;
379350 }
380351 result .put (e .getKey (), e .getValue ().hidingPrivate ().withGenericTypeParams (typeParams ));
381352 }
353+
382354 }
383355
384356 public static void addHidingPrivate (Multimap <String , DefLink > result , Multimap <String , DefLink > adding ) {
@@ -388,6 +360,7 @@ public static void addHidingPrivate(Multimap<String, DefLink> result, Multimap<S
388360 }
389361 result .put (e .getKey (), e .getValue ().hidingPrivate ());
390362 }
363+
391364 }
392365
393366 public static void addHidingPrivateAndProtected (ImmutableMultimap .Builder <String , DefLink > r , Multimap <String , ? extends DefLink > adding ) {
@@ -416,12 +389,4 @@ public static ImmutableMultimap<String, DefLink> calculate(ExprClosure e) {
416389 return result .build ();
417390 }
418391
419- // OPTIMIZATION 11: Clear cache method for when packages change
420- public static void clearPackageCache () {
421- packageNameLinksCache .clear ();
422- }
423-
424- public static void clearPackageCache (WPackage p ) {
425- packageNameLinksCache .remove (p );
426- }
427392}
0 commit comments