|
2 | 2 |
|
3 | 3 | import com.google.common.collect.ImmutableCollection; |
4 | 4 | import com.google.common.collect.ImmutableList; |
| 5 | +import de.peeeq.wurstscript.WLogger; |
5 | 6 | import de.peeeq.wurstscript.ast.*; |
6 | 7 | import de.peeeq.wurstscript.types.*; |
7 | 8 | import de.peeeq.wurstscript.utils.Utils; |
|
11 | 12 | import java.util.*; |
12 | 13 |
|
13 | 14 | public class NameResolution { |
| 15 | + private static String memberFuncCacheName(String name, WurstType receiverType) { |
| 16 | + return name |
| 17 | + + "@" |
| 18 | + + receiverType |
| 19 | + + "#" |
| 20 | + + System.identityHashCode(receiverType); |
| 21 | + } |
14 | 22 |
|
15 | 23 | public static ImmutableCollection<FuncLink> lookupFuncsNoConfig(Element node, String name, boolean showErrors) { |
16 | 24 | if (!showErrors) { |
@@ -117,16 +125,41 @@ private static <T extends NameLink> ImmutableCollection<T> removeDuplicates(List |
117 | 125 |
|
118 | 126 | public static ImmutableCollection<FuncLink> lookupMemberFuncs(Element node, WurstType receiverType, String name, boolean showErrors) { |
119 | 127 | if (!showErrors) { |
120 | | - GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, name + "@" + receiverType, GlobalCaches.LookupType.MEMBER_FUNC); |
| 128 | + GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, memberFuncCacheName(name, receiverType), GlobalCaches.LookupType.MEMBER_FUNC); |
121 | 129 | @SuppressWarnings("unchecked") |
122 | 130 | ImmutableCollection<FuncLink> cached = (ImmutableCollection<FuncLink>) GlobalCaches.lookupCache.get(key); |
123 | 131 | if (cached != null) { |
| 132 | + WLogger.trace("[LOOKUPCACHE] HIT MEMBER_FUNC node=" + System.identityHashCode(node) |
| 133 | + + " name=" + name |
| 134 | + + " recv=" + receiverType |
| 135 | + + " recvId=" + System.identityHashCode(receiverType) |
| 136 | + + " size=" + cached.size()); |
124 | 137 | return cached; |
125 | 138 | } |
126 | 139 | } |
127 | 140 |
|
128 | 141 | List<FuncLink> result = new ArrayList<>(4); |
129 | | - addMemberMethods(node, receiverType, name, result); |
| 142 | + WLogger.trace("[LMF] addMemberMethods recv=" + receiverType |
| 143 | + + " recvId=" + System.identityHashCode(receiverType) |
| 144 | + + " name=" + name |
| 145 | + + " node=" + System.identityHashCode(node)); |
| 146 | + // Collect from the type first, but *validate/adapt* each candidate to the actual receiverType. |
| 147 | + List<FuncLink> fromType = new ArrayList<>(4); |
| 148 | + addMemberMethods(node, receiverType, name, fromType); |
| 149 | + for (FuncLink cand : fromType) { |
| 150 | + DefLink m = matchDefLinkReceiver(cand, receiverType, node, showErrors); |
| 151 | + if (m instanceof FuncLink) { |
| 152 | + result.add((FuncLink) m); |
| 153 | + } |
| 154 | + } |
| 155 | + |
| 156 | + for (FuncLink f : result) { |
| 157 | + WLogger.trace("[LMF] addMemberMethods -> " + f |
| 158 | + + " recv=" + f.getReceiverType() |
| 159 | + + " recvId=" + System.identityHashCode(f.getReceiverType()) |
| 160 | + + " linkVB=" + f.getVariableBinding() |
| 161 | + + " linkTypeParams=" + f.getTypeParams()); |
| 162 | + } |
130 | 163 |
|
131 | 164 | WScope scope = node.attrNearestScope(); |
132 | 165 |
|
@@ -155,7 +188,12 @@ public static ImmutableCollection<FuncLink> lookupMemberFuncs(Element node, Wurs |
155 | 188 | ImmutableCollection<FuncLink> immutableResult = removeDuplicates(result); |
156 | 189 |
|
157 | 190 | if (!showErrors) { |
158 | | - GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, name + "@" + receiverType, GlobalCaches.LookupType.MEMBER_FUNC); |
| 191 | + GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, memberFuncCacheName(name, receiverType), GlobalCaches.LookupType.MEMBER_FUNC); |
| 192 | + WLogger.trace("[LOOKUPCACHE] PUT MEMBER_FUNC node=" + System.identityHashCode(node) |
| 193 | + + " name=" + name |
| 194 | + + " recv=" + receiverType |
| 195 | + + " recvId=" + System.identityHashCode(receiverType) |
| 196 | + + " size=" + immutableResult.size()); |
159 | 197 | GlobalCaches.lookupCache.put(key, immutableResult); |
160 | 198 | } |
161 | 199 |
|
@@ -252,7 +290,7 @@ public static NameLink lookupVarNoConfig(Element node, String name, boolean show |
252 | 290 |
|
253 | 291 | public static NameLink lookupMemberVar(Element node, WurstType receiverType, String name, boolean showErrors) { |
254 | 292 | if (!showErrors) { |
255 | | - GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, name + "@" + receiverType, GlobalCaches.LookupType.MEMBER_VAR); |
| 293 | + GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, memberFuncCacheName(name, receiverType), GlobalCaches.LookupType.MEMBER_VAR); |
256 | 294 | NameLink cached = (NameLink) GlobalCaches.lookupCache.get(key); |
257 | 295 | if (cached != null) { |
258 | 296 | return cached; |
@@ -286,7 +324,11 @@ public static NameLink lookupMemberVar(Element node, WurstType receiverType, Str |
286 | 324 |
|
287 | 325 | if (bestMatch != null) { |
288 | 326 | if (!showErrors) { |
289 | | - GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, name + "@" + receiverType, GlobalCaches.LookupType.MEMBER_VAR); |
| 327 | + GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, memberFuncCacheName(name, receiverType), GlobalCaches.LookupType.MEMBER_VAR); |
| 328 | + WLogger.trace("[LOOKUPCACHE] PUT MEMBER_FUNC node=" + System.identityHashCode(node) |
| 329 | + + " name=" + name |
| 330 | + + " recv=" + receiverType |
| 331 | + + " recvId=" + System.identityHashCode(receiverType)); |
290 | 332 | GlobalCaches.lookupCache.put(key, bestMatch.link); |
291 | 333 | } |
292 | 334 | return bestMatch.link; |
@@ -412,24 +454,43 @@ private DefLinkMatch(DefLink link, int distance) { |
412 | 454 | } |
413 | 455 |
|
414 | 456 | public static DefLink matchDefLinkReceiver(DefLink n, WurstType receiverType, Element node, boolean showErrors) { |
415 | | - WurstType n_receiverType = n.getReceiverType(); |
416 | | - if (n_receiverType == null) { |
417 | | - return null; |
418 | | - } |
419 | | - VariableBinding mapping = receiverType.matchAgainstSupertype(n_receiverType, node, VariableBinding.emptyMapping().withTypeVariables(n.getTypeParams()), VariablePosition.RIGHT); |
420 | | - if (mapping == null) { |
421 | | - return null; |
422 | | - } |
| 457 | + WurstType candRecv = n.getReceiverType(); |
| 458 | + if (candRecv == null) return null; |
| 459 | + |
| 460 | + VariableBinding seed = VariableBinding.emptyMapping().withTypeVariables(n.getTypeParams()); |
| 461 | + VariableBinding mapping = receiverType.matchAgainstSupertype(candRecv, node, seed, VariablePosition.RIGHT); |
| 462 | + if (mapping == null) return null; |
| 463 | + |
| 464 | + WLogger.trace("[MATCHRECV] def=" + ((n instanceof FuncLink) ? ((FuncLink) n).getDef().getName() : n.getDef().getName()) |
| 465 | + + " left=" + receiverType |
| 466 | + + " candRecv=" + candRecv |
| 467 | + + " linkTypeParams=" + n.getTypeParams() |
| 468 | + + (n instanceof FuncLink ? (" linkVB=" + ((FuncLink) n).getVariableBinding()) : "")); |
| 469 | + |
423 | 470 | if (showErrors) { |
424 | 471 | if (n.getVisibility() == Visibility.PRIVATE_OTHER) { |
425 | 472 | node.addError(Utils.printElement(n.getDef()) + " is private and cannot be used here."); |
426 | | - } else if (n.getVisibility() == Visibility.PROTECTED_OTHER && !receiverType.isSubtypeOf(n_receiverType, node)) { |
| 473 | + } else if (n.getVisibility() == Visibility.PROTECTED_OTHER && !receiverType.isSubtypeOf(candRecv, node)) { |
427 | 474 | node.addError(Utils.printElement(n.getDef()) + " is protected and cannot be used here."); |
428 | 475 | } |
429 | 476 | } |
| 477 | + |
430 | 478 | return n.withTypeArgBinding(node, mapping); |
431 | 479 | } |
432 | 480 |
|
| 481 | + private static Iterable<TypeParamDef> typeParamsOfReceiverType(WurstType t) { |
| 482 | + if (t instanceof WurstTypeClassOrInterface) { |
| 483 | + return ((WurstTypeClassOrInterface) t).getDef().getTypeParameters(); |
| 484 | + } |
| 485 | + if (t instanceof WurstTypeClass) { |
| 486 | + return ((WurstTypeClass) t).getClassDef().getTypeParameters(); |
| 487 | + } |
| 488 | + if (t instanceof WurstTypeInterface) { |
| 489 | + return ((WurstTypeInterface) t).getInterfaceDef().getTypeParameters(); |
| 490 | + } |
| 491 | + return java.util.Collections.emptyList(); |
| 492 | + } |
| 493 | + |
433 | 494 | public static @Nullable TypeDef lookupType(Element node, String name, boolean showErrors) { |
434 | 495 | if (!showErrors) { |
435 | 496 | GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, name, GlobalCaches.LookupType.TYPE); |
|
0 commit comments