MCPcopy Create free account
hub / github.com/DeusData/codebase-memory-mcp / propagate_template

Function propagate_template

internal/cbm/lsp/java_lsp.c:2355–2406  ·  view source on GitHub ↗

When a method on a TEMPLATE receiver returns a NAMED type that is itself * a parametric "carrier" (Stream, Iterator, Optional, …), preserve the * receiver's element type so chained lambda inference keeps working. * * This is the fix for `xs.stream().filter(x -> x.foo())` losing track of * String inside the filter lambda — without propagation, stream() would * return bare NAMED(Stream) with n

Source from the content-addressed store, hash-verified

2353 * return bare NAMED(Stream) with no template args, and the SAM binder
2354 * couldn't substitute T0. */
2355static const CBMType *propagate_template(CBMArena *a, const char *recv_qn, const char *method_name,
2356 const CBMType *const *recv_targs, int recv_targ_count,
2357 const CBMType *return_t) {
2358 if (!return_t || return_t->kind != CBM_TYPE_NAMED)
2359 return return_t;
2360 if (recv_targ_count <= 0 || !recv_targs)
2361 return return_t;
2362 const char *ret_qn = return_t->data.named.qualified_name;
2363 if (!ret_qn)
2364 return return_t;
2365
2366 /* Carriers that preserve T0. */
2367 static const char *t0_carriers[] = {
2368 "java.util.stream.Stream", "java.util.Iterator", "java.util.ListIterator",
2369 "java.util.Spliterator", "java.util.Optional", "java.util.List",
2370 "java.util.Set", "java.util.Collection", "java.lang.Iterable",
2371 "java.util.Queue", "java.util.Deque", NULL,
2372 };
2373 bool is_t0 = false;
2374 for (int i = 0; t0_carriers[i]; i++) {
2375 if (strcmp(t0_carriers[i], ret_qn) == 0) {
2376 is_t0 = true;
2377 break;
2378 }
2379 }
2380 if (is_t0) {
2381 const CBMType **args = (const CBMType **)cbm_arena_alloc(a, 2 * sizeof(*args));
2382 if (!args)
2383 return return_t;
2384 args[0] = recv_targs[0];
2385 args[1] = NULL;
2386 return cbm_type_template(a, ret_qn, args, 1);
2387 }
2388
2389 /* Map.keySet → Set<K>, Map.values → Collection<V>, Map.entrySet → Set<Entry<K,V>>. */
2390 if (is_map_like(recv_qn) && recv_targ_count >= 2) {
2391 const CBMType **args = (const CBMType **)cbm_arena_alloc(a, 2 * sizeof(*args));
2392 if (!args)
2393 return return_t;
2394 if (strcmp(method_name, "keySet") == 0) {
2395 args[0] = recv_targs[0];
2396 args[1] = NULL;
2397 return cbm_type_template(a, "java.util.Set", args, 1);
2398 }
2399 if (strcmp(method_name, "values") == 0) {
2400 args[0] = recv_targs[1];
2401 args[1] = NULL;
2402 return cbm_type_template(a, "java.util.Collection", args, 1);
2403 }
2404 }
2405 return return_t;
2406}
2407
2408/* Given a method-invocation node and its resolved CBMRegisteredFunc, walk
2409 * each lambda argument: bind its formal_parameters to the SAM's parameter

Callers 1

eval_method_invocationFunction · 0.85

Calls 3

cbm_type_templateFunction · 0.85
is_map_likeFunction · 0.85
cbm_arena_allocFunction · 0.50

Tested by

no test coverage detected