@@ -515,6 +515,7 @@ fn emit_js_prototype_method(class_name: &str, method_name: &str, rhs: &Node, sou
515515 let full_name = format ! ( "{}.{}" , class_name, method_name) ;
516516 match rhs. kind ( ) {
517517 "function_expression" | "arrow_function" => {
518+ let children = extract_js_parameters ( rhs, source) ;
518519 symbols. definitions . push ( Definition {
519520 name : full_name,
520521 kind : "method" . to_string ( ) ,
@@ -523,7 +524,7 @@ fn emit_js_prototype_method(class_name: &str, method_name: &str, rhs: &Node, sou
523524 decorators : None ,
524525 complexity : compute_all_metrics ( rhs, source, "javascript" ) ,
525526 cfg : build_function_cfg ( rhs, "javascript" , source) ,
526- children : None ,
527+ children : opt_children ( children ) ,
527528 } ) ;
528529 }
529530 "identifier" => {
@@ -545,6 +546,7 @@ fn extract_js_prototype_object_literal(class_name: &str, obj_node: &Node, source
545546 match child. kind ( ) {
546547 "method_definition" => {
547548 let Some ( name_node) = child. child_by_field_name ( "name" ) else { continue } ;
549+ let children = extract_js_parameters ( & child, source) ;
548550 symbols. definitions . push ( Definition {
549551 name : format ! ( "{}.{}" , class_name, node_text( & name_node, source) ) ,
550552 kind : "method" . to_string ( ) ,
@@ -553,7 +555,7 @@ fn extract_js_prototype_object_literal(class_name: &str, obj_node: &Node, source
553555 decorators : None ,
554556 complexity : compute_all_metrics ( & child, source, "javascript" ) ,
555557 cfg : build_function_cfg ( & child, "javascript" , source) ,
556- children : None ,
558+ children : opt_children ( children ) ,
557559 } ) ;
558560 }
559561 "shorthand_property_identifier" => {
@@ -2691,6 +2693,82 @@ mod tests {
26912693 assert ! ( def. is_none( ) , "built-in prototype assignment should be ignored; got: {:?}" , def) ;
26922694 }
26932695
2696+ #[ test]
2697+ fn prototype_direct_method_has_complexity_cfg_and_children ( ) {
2698+ let s = parse_js (
2699+ "function C() {}\n \
2700+ C.prototype.foo = function(x, y) { if (true) { return 1; } return 0; };",
2701+ ) ;
2702+ let def = s. definitions . iter ( ) . find ( |d| d. name == "C.foo" ) . expect ( "C.foo missing" ) ;
2703+ assert ! ( def. complexity. is_some( ) , "C.foo should have complexity metrics" ) ;
2704+ assert ! ( def. cfg. is_some( ) , "C.foo should have CFG data" ) ;
2705+ let children = def. children . as_deref ( ) . unwrap_or ( & [ ] ) ;
2706+ assert ! (
2707+ children. iter( ) . any( |c| c. name == "x" ) ,
2708+ "C.foo should have parameter 'x'; got: {:?}" , children
2709+ ) ;
2710+ assert ! (
2711+ children. iter( ) . any( |c| c. name == "y" ) ,
2712+ "C.foo should have parameter 'y'; got: {:?}" , children
2713+ ) ;
2714+ }
2715+
2716+ #[ test]
2717+ fn prototype_direct_arrow_has_complexity_cfg_and_children ( ) {
2718+ let s = parse_js (
2719+ "function C() {}\n \
2720+ C.prototype.bar = (a, b) => a > 0 ? a : b;",
2721+ ) ;
2722+ let def = s. definitions . iter ( ) . find ( |d| d. name == "C.bar" ) . expect ( "C.bar missing" ) ;
2723+ assert ! ( def. complexity. is_some( ) , "C.bar arrow should have complexity metrics" ) ;
2724+ assert ! ( def. cfg. is_some( ) , "C.bar arrow should have CFG data" ) ;
2725+ let children = def. children . as_deref ( ) . unwrap_or ( & [ ] ) ;
2726+ assert ! (
2727+ children. iter( ) . any( |c| c. name == "a" ) ,
2728+ "C.bar should have parameter 'a'; got: {:?}" , children
2729+ ) ;
2730+ assert ! (
2731+ children. iter( ) . any( |c| c. name == "b" ) ,
2732+ "C.bar should have parameter 'b'; got: {:?}" , children
2733+ ) ;
2734+ }
2735+
2736+ #[ test]
2737+ fn prototype_object_literal_method_definition_has_complexity_cfg_and_children ( ) {
2738+ let s = parse_js (
2739+ "function C() {}\n \
2740+ C.prototype = {\n \
2741+ greet(name) { if (true) { return 'hi'; } return ''; },\n \
2742+ };",
2743+ ) ;
2744+ let def = s. definitions . iter ( ) . find ( |d| d. name == "C.greet" ) . expect ( "C.greet missing" ) ;
2745+ assert ! ( def. complexity. is_some( ) , "C.greet should have complexity metrics" ) ;
2746+ assert ! ( def. cfg. is_some( ) , "C.greet should have CFG data" ) ;
2747+ let children = def. children . as_deref ( ) . unwrap_or ( & [ ] ) ;
2748+ assert ! (
2749+ children. iter( ) . any( |c| c. name == "name" ) ,
2750+ "C.greet should have parameter 'name'; got: {:?}" , children
2751+ ) ;
2752+ }
2753+
2754+ #[ test]
2755+ fn prototype_object_literal_pair_fn_has_complexity_cfg_and_children ( ) {
2756+ let s = parse_js (
2757+ "function C() {}\n \
2758+ C.prototype = {\n \
2759+ bar: function(n) { if (true) { return 1; } return 0; },\n \
2760+ };",
2761+ ) ;
2762+ let def = s. definitions . iter ( ) . find ( |d| d. name == "C.bar" ) . expect ( "C.bar missing" ) ;
2763+ assert ! ( def. complexity. is_some( ) , "C.bar should have complexity metrics" ) ;
2764+ assert ! ( def. cfg. is_some( ) , "C.bar should have CFG data" ) ;
2765+ let children = def. children . as_deref ( ) . unwrap_or ( & [ ] ) ;
2766+ assert ! (
2767+ children. iter( ) . any( |c| c. name == "n" ) ,
2768+ "C.bar should have parameter 'n'; got: {:?}" , children
2769+ ) ;
2770+ }
2771+
26942772 /// Phase 8.3e: Object.defineProperty seeds composite type_map key.
26952773 #[ test]
26962774 fn type_map_from_define_property ( ) {
0 commit comments