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

Function propagate_template

internal/cbm/lsp/java_lsp.c:2290–2341  ·  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

2288 * return bare NAMED(Stream) with no template args, and the SAM binder
2289 * couldn't substitute T0. */
2290static const CBMType *propagate_template(CBMArena *a, const char *recv_qn, const char *method_name,
2291 const CBMType *const *recv_targs, int recv_targ_count,
2292 const CBMType *return_t) {
2293 if (!return_t || return_t->kind != CBM_TYPE_NAMED)
2294 return return_t;
2295 if (recv_targ_count <= 0 || !recv_targs)
2296 return return_t;
2297 const char *ret_qn = return_t->data.named.qualified_name;
2298 if (!ret_qn)
2299 return return_t;
2300
2301 /* Carriers that preserve T0. */
2302 static const char *t0_carriers[] = {
2303 "java.util.stream.Stream", "java.util.Iterator", "java.util.ListIterator",
2304 "java.util.Spliterator", "java.util.Optional", "java.util.List",
2305 "java.util.Set", "java.util.Collection", "java.lang.Iterable",
2306 "java.util.Queue", "java.util.Deque", NULL,
2307 };
2308 bool is_t0 = false;
2309 for (int i = 0; t0_carriers[i]; i++) {
2310 if (strcmp(t0_carriers[i], ret_qn) == 0) {
2311 is_t0 = true;
2312 break;
2313 }
2314 }
2315 if (is_t0) {
2316 const CBMType **args = (const CBMType **)cbm_arena_alloc(a, 2 * sizeof(*args));
2317 if (!args)
2318 return return_t;
2319 args[0] = recv_targs[0];
2320 args[1] = NULL;
2321 return cbm_type_template(a, ret_qn, args, 1);
2322 }
2323
2324 /* Map.keySet → Set<K>, Map.values → Collection<V>, Map.entrySet → Set<Entry<K,V>>. */
2325 if (is_map_like(recv_qn) && recv_targ_count >= 2) {
2326 const CBMType **args = (const CBMType **)cbm_arena_alloc(a, 2 * sizeof(*args));
2327 if (!args)
2328 return return_t;
2329 if (strcmp(method_name, "keySet") == 0) {
2330 args[0] = recv_targs[0];
2331 args[1] = NULL;
2332 return cbm_type_template(a, "java.util.Set", args, 1);
2333 }
2334 if (strcmp(method_name, "values") == 0) {
2335 args[0] = recv_targs[1];
2336 args[1] = NULL;
2337 return cbm_type_template(a, "java.util.Collection", args, 1);
2338 }
2339 }
2340 return return_t;
2341}
2342
2343/* Given a method-invocation node and its resolved CBMRegisteredFunc, walk
2344 * 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