Skip to content

function_name does not work with C++... potential solution #41

@sheam

Description

@sheam

Description

The function-name statusline element never displays when editing C or C++ files. The
cursor can be anywhere inside a named function body and the element remains blank.

Steps to reproduce

  1. Add function-name to [editor.statusline] left in config.toml
  2. Open any .cpp or .c file
  3. Place cursor inside a named function, e.g.:
bool trace::is_valid() const {
    // cursor here
}
  1. Observe that the statusline shows nothing for function-name

Root cause

get_current_function_name() in helix-term/src/ui/statusline.rs walks up the
syntax tree and, upon finding a function-like node (kind containing "function"),
only checks direct children for identifier or field_identifier:

for i in 0..node.child_count() {
    if let Some(child) = node.child(i) {
        if child.kind() == "identifier" || child.kind() == "field_identifier" {
            return Some(name);
        }
    }
}

This works for Go, Rust, and TypeScript because those languages place the function
name as a direct child of the function node. In C/C++ however, the tree-sitter
grammar nests the name inside a declarator chain:

 function_definition           ← matched (contains "function")
 ├── primitive_type "bool"
 ├── function_declarator       ← NOT an identifier
 │   ├── qualified_identifier  ← NOT an identifier
 │   │   ├── namespace_identifier "trace"
 │   │   └── identifier "is_valid"   ← actual name, 2–3 levels deep
 │   └── parameter_list
 └── compound_statement        ← cursor is here

None of function_definition's direct children have kind identifier or
field_identifier, so no name is returned.

Suggested fix

After the existing direct-child check fails, add a fallback that walks into any
*declarator child and extracts the identifier from the declarator chain. A
recursive helper handles the cases:

  • function_declarator → recurse into children
  • qualified_identifier → return the last identifier child (strips namespace prefix)
  • identifier / field_identifier → return directly

This covers simple functions (void foo()), qualified methods
(bool trace::is_valid() const), and deeper nesting (ns1::ns2::Class::method()).

Affected languages

C, C++ — and potentially any other language whose tree-sitter grammar places the
function name inside a *_declarator node rather than as a direct child of the
function definition node.

Languages confirmed working

Language Node kind Name location
Go function_declaration Direct identifier child
Rust function_item Direct identifier child
TypeScript function_declaration Direct identifier child
TypeScript arrow_function Parent variable_declarator lookup

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions