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