| 1981 | } |
| 1982 | |
| 1983 | static void resolve_method_call(JavaLSPContext *ctx, TSNode call) { |
| 1984 | TSNode obj = ts_node_child_by_field_name(call, "object", 6); |
| 1985 | TSNode name_node = ts_node_child_by_field_name(call, "name", 4); |
| 1986 | if (ts_node_is_null(name_node)) |
| 1987 | return; |
| 1988 | char *mname = java_node_text(ctx, name_node); |
| 1989 | if (!mname) |
| 1990 | return; |
| 1991 | int arity = count_call_args(call); |
| 1992 | |
| 1993 | /* Bare call: `foo()`. */ |
| 1994 | if (ts_node_is_null(obj)) { |
| 1995 | if (ctx->enclosing_class_qn) { |
| 1996 | const CBMRegisteredFunc *f = |
| 1997 | java_lookup_method(ctx, ctx->enclosing_class_qn, mname, arity); |
| 1998 | if (f) { |
| 1999 | const char *strategy = "lsp_type_dispatch"; |
| 2000 | if (f->receiver_type && strcmp(f->receiver_type, ctx->enclosing_class_qn) != 0) { |
| 2001 | strategy = "lsp_inherited_dispatch"; |
| 2002 | } |
| 2003 | java_emit_resolved(ctx, f->qualified_name, strategy, 0.95f); |
| 2004 | return; |
| 2005 | } |
| 2006 | } |
| 2007 | /* JLS §15.12.1: a bare call inside an inner class also looks up the |
| 2008 | * call against each enclosing-class scope. Walk outer classes. */ |
| 2009 | for (int i = ctx->enclosing_class_depth - 2; i >= 0; i--) { |
| 2010 | const char *outer = ctx->enclosing_class_stack[i]; |
| 2011 | if (!outer) |
| 2012 | continue; |
| 2013 | const CBMRegisteredFunc *f = java_lookup_method(ctx, outer, mname, arity); |
| 2014 | if (f) { |
| 2015 | java_emit_resolved(ctx, f->qualified_name, "lsp_outer_dispatch", 0.92f); |
| 2016 | return; |
| 2017 | } |
| 2018 | } |
| 2019 | /* Static import. */ |
| 2020 | for (int i = 0; i < ctx->import_count; i++) { |
| 2021 | if (ctx->import_kinds[i] != CBM_JAVA_IMPORT_STATIC) |
| 2022 | continue; |
| 2023 | if (strcmp(ctx->import_local_names[i], mname) != 0) |
| 2024 | continue; |
| 2025 | const char *target = ctx->import_target_qns[i]; |
| 2026 | const char *last_dot = strrchr(target, '.'); |
| 2027 | if (!last_dot) |
| 2028 | continue; |
| 2029 | char *cls = cbm_arena_strndup(ctx->arena, target, (size_t)(last_dot - target)); |
| 2030 | const CBMRegisteredFunc *f = java_lookup_method(ctx, cls, mname, arity); |
| 2031 | if (!f && ctx->registry) { |
| 2032 | /* The import is written package-qualified ("demo.Util"), but the |
| 2033 | * class is registered under the project/directory QN |
| 2034 | * ("<proj>.Util") when the `package` declaration and the file's |
| 2035 | * directory differ. Resolve the import's class by its short name |
| 2036 | * against the registry and retry — preferring an in-module match. |
| 2037 | * Mirrors the C++ short-name type fallback. */ |
| 2038 | const char *cls_dot = strrchr(cls, '.'); |
| 2039 | const char *cls_short = cls_dot ? cls_dot + 1 : cls; |
| 2040 | size_t sl = strlen(cls_short); |
no test coverage detected