extractClassMembers (r.ts:110-163): arguments in source order with a positional counter — ggproto's 2nd positional identifier and `inherit`/`contains` named args become `extends` refs (from the CLASS row, positioned at the VALUE node); named function_definition args and `list(…)` entries become methods. Non-method argument subtrees are NEVER visited (`representation(…)`, `signature(…)` invisible).
(&mut self, class_call: Node<'t>, class_row: u32)
| 477 | /// `list(…)` entries become methods. Non-method argument subtrees are |
| 478 | /// NEVER visited (`representation(…)`, `signature(…)` invisible). |
| 479 | fn extract_class_members(&mut self, class_call: Node<'t>, class_row: u32) { |
| 480 | let args = match class_call.child_by_field_name("arguments") { |
| 481 | Some(a) => a, |
| 482 | None => return, |
| 483 | }; |
| 484 | let mut positional = 0u32; |
| 485 | let mut cursor = args.walk(); |
| 486 | let arg_nodes: Vec<Node<'t>> = args.named_children(&mut cursor).collect(); |
| 487 | for arg in arg_nodes { |
| 488 | if arg.kind() != "argument" { |
| 489 | continue; |
| 490 | } |
| 491 | let arg_name = arg.child_by_field_name("name"); |
| 492 | let value = arg.child_by_field_name("value"); |
| 493 | let arg_name = match arg_name { |
| 494 | None => { |
| 495 | positional += 1; |
| 496 | if positional == 2 { |
| 497 | if let Some(v) = value { |
| 498 | if v.kind() == "identifier" { |
| 499 | let parent = self.text(v).to_string(); |
| 500 | self.push_ref_at(class_row, &parent, "extends", v); |
| 501 | } |
| 502 | } |
| 503 | } |
| 504 | continue; |
| 505 | } |
| 506 | Some(n) => n, |
| 507 | }; |
| 508 | let arg_name_text = self.text(arg_name); |
| 509 | // R6 `inherit = Parent` / S4 `contains = "Parent"` — a falsy |
| 510 | // resolution (`inherit = pkg::Parent`, empty string) emits nothing. |
| 511 | if (arg_name_text == "inherit" || arg_name_text == "contains") && value.is_some() { |
| 512 | if let Some(parent) = self.literal_or_identifier(value) { |
| 513 | if !parent.is_empty() { |
| 514 | let parent = parent.to_string(); |
| 515 | self.push_ref_at(class_row, &parent, "extends", value.unwrap()); |
| 516 | } |
| 517 | } |
| 518 | continue; |
| 519 | } |
| 520 | // Direct named function argument (ggproto methods). |
| 521 | if let Some(v) = value { |
| 522 | if v.kind() == "function_definition" { |
| 523 | self.emit_method_arg(arg); |
| 524 | continue; |
| 525 | } |
| 526 | // list(…) of named function arguments (R5/R6 methods). |
| 527 | if v.kind() == "call" && self.callee_name(v) == Some("list") { |
| 528 | if let Some(list_args) = v.child_by_field_name("arguments") { |
| 529 | let mut lc = list_args.walk(); |
| 530 | let entries: Vec<Node<'t>> = list_args.named_children(&mut lc).collect(); |
| 531 | for entry in entries { |
| 532 | if entry.kind() == "argument" { |
| 533 | self.emit_method_arg(entry); |
| 534 | } |
| 535 | } |
| 536 | } |
no test coverage detected