Resolve the name node for a function, handling language-specific quirks. Uses a loop to handle template_declaration unwrapping (avoids recursion).
| 681 | // Resolve the name node for a function, handling language-specific quirks. |
| 682 | // Uses a loop to handle template_declaration unwrapping (avoids recursion). |
| 683 | TSNode cbm_resolve_func_name(TSNode node, CBMLanguage lang) { |
| 684 | enum { MAX_TEMPLATE_DEPTH = 2 }; |
| 685 | for (int tmpl_depth = 0; tmpl_depth < MAX_TEMPLATE_DEPTH; tmpl_depth++) { |
| 686 | const char *kind = ts_node_type(node); |
| 687 | |
| 688 | if (lang == CBM_LANG_HASKELL && strcmp(kind, "signature") == 0) { |
| 689 | TSNode null_node = {0}; |
| 690 | return null_node; |
| 691 | } |
| 692 | |
| 693 | // A parameterized ObjectScript routine wraps its tag and body in a |
| 694 | // procedure node. Use the direct tag as the callable name so the |
| 695 | // definition spans the complete procedure instead of only its label. |
| 696 | if (lang == CBM_LANG_OBJECTSCRIPT_ROUTINE && |
| 697 | (strcmp(kind, "tag") == 0 || strcmp(kind, "procedure") == 0)) { |
| 698 | return strcmp(kind, "tag") == 0 ? node : cbm_find_child_by_kind(node, "tag"); |
| 699 | } |
| 700 | // ObjectScript method/classmethod: name lives under method_definition -> |
| 701 | // method_name -> first named child. |
| 702 | if (lang == CBM_LANG_OBJECTSCRIPT_UDL && |
| 703 | (strcmp(kind, "method") == 0 || strcmp(kind, "classmethod") == 0)) { |
| 704 | TSNode mdef = cbm_find_child_by_kind(node, "method_definition"); |
| 705 | if (!ts_node_is_null(mdef)) { |
| 706 | TSNode mname = cbm_find_child_by_kind(mdef, "method_name"); |
| 707 | if (!ts_node_is_null(mname) && ts_node_named_child_count(mname) > 0) { |
| 708 | return ts_node_named_child(mname, 0); |
| 709 | } |
| 710 | } |
| 711 | TSNode null_node = {0}; |
| 712 | return null_node; |
| 713 | } |
| 714 | if (lang == CBM_LANG_OBJECTSCRIPT_UDL && strcmp(kind, "query") == 0) { |
| 715 | return cbm_find_child_by_kind(node, "query_name"); |
| 716 | } |
| 717 | |
| 718 | TSNode name = func_name_node(node); |
| 719 | |
| 720 | if (lang == CBM_LANG_R && strcmp(kind, "function_definition") == 0) { |
| 721 | return resolve_r_func_name(node); |
| 722 | } |
| 723 | |
| 724 | if (!ts_node_is_null(name)) { |
| 725 | return name; |
| 726 | } |
| 727 | |
| 728 | /* Swift and newer tree-sitter-kotlin: function_declaration has no `name` |
| 729 | * field; the function name is a `simple_identifier` child. */ |
| 730 | if ((lang == CBM_LANG_SWIFT || lang == CBM_LANG_KOTLIN) && |
| 731 | strcmp(kind, "function_declaration") == 0) { |
| 732 | TSNode si = cbm_find_child_by_kind(node, "simple_identifier"); |
| 733 | if (!ts_node_is_null(si)) { |
| 734 | return si; |
| 735 | } |
| 736 | } |
| 737 | |
| 738 | // PowerShell function_statement has no `name` field; the name is a |
| 739 | // `function_name` child node (#35). |
| 740 | if (lang == CBM_LANG_POWERSHELL && strcmp(kind, "function_statement") == 0) { |
no test coverage detected