Direct identifiers and direct, statically-named TS member values passed as * arguments are narrow syntactic candidates only. A language LSP must still * prove one target at this exact occurrence before the graph upgrades USAGE to * CALL_REFERENCE; unresolved, reassigned, and composite expressions stay USAGE. */
| 1416 | * prove one target at this exact occurrence before the graph upgrades USAGE to |
| 1417 | * CALL_REFERENCE; unresolved, reassigned, and composite expressions stay USAGE. */ |
| 1418 | static TSNode csharp_callable_value_site(TSNode node) { |
| 1419 | usage_slow_parent_fallback_test_note(); |
| 1420 | const char *kind = ts_node_type(node); |
| 1421 | if (strcmp(kind, "identifier") != 0 && strcmp(kind, "simple_identifier") != 0) { |
| 1422 | return (TSNode){0}; |
| 1423 | } |
| 1424 | |
| 1425 | TSNode site = node; |
| 1426 | TSNode parent = ts_node_parent(site); |
| 1427 | if (!ts_node_is_null(parent) && strcmp(ts_node_type(parent), "generic_name") == 0) { |
| 1428 | TSNode name = ts_node_child_by_field_name(parent, TS_FIELD("name")); |
| 1429 | if (ts_node_is_null(name) && ts_node_named_child_count(parent) > 0) { |
| 1430 | name = ts_node_named_child(parent, 0); |
| 1431 | } |
| 1432 | if (ts_node_is_null(name) || !ts_node_eq(name, node)) { |
| 1433 | return (TSNode){0}; |
| 1434 | } |
| 1435 | site = parent; |
| 1436 | parent = ts_node_parent(site); |
| 1437 | } |
| 1438 | |
| 1439 | if (!ts_node_is_null(parent) && strcmp(ts_node_type(parent), "member_access_expression") == 0) { |
| 1440 | TSNode member = ts_node_child_by_field_name(parent, TS_FIELD("name")); |
| 1441 | if (ts_node_is_null(member) || !ts_node_eq(member, site)) { |
| 1442 | return (TSNode){0}; |
| 1443 | } |
| 1444 | site = parent; |
| 1445 | parent = ts_node_parent(site); |
| 1446 | } |
| 1447 | |
| 1448 | while (!ts_node_is_null(parent) && |
| 1449 | strcmp(ts_node_type(parent), "parenthesized_expression") == 0) { |
| 1450 | TSNode inner = ts_node_child_by_field_name(parent, TS_FIELD("expression")); |
| 1451 | if (ts_node_is_null(inner) && ts_node_named_child_count(parent) == 1) { |
| 1452 | inner = ts_node_named_child(parent, 0); |
| 1453 | } |
| 1454 | if (ts_node_is_null(inner) || !ts_node_eq(inner, site)) { |
| 1455 | return (TSNode){0}; |
| 1456 | } |
| 1457 | site = parent; |
| 1458 | parent = ts_node_parent(site); |
| 1459 | } |
| 1460 | |
| 1461 | /* The wrapper chain proves admission, but the semantic row is keyed to the |
| 1462 | * terminal method-name identifier. Keep the raw carrier on that leaf. */ |
| 1463 | return is_direct_argument_value(site) ? node : (TSNode){0}; |
| 1464 | } |
| 1465 | |
| 1466 | /* Climb out of the parentheses wrapping a direct argument and return the |
| 1467 | * outermost wrapper, or null when the node is not a parenthesised direct |
no test coverage detected