Coverage Report

Created: 2025-09-05 15:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/noah/src/ruchy/src/backend/transpiler/method_call_refactored.rs
Line
Count
Source
1
//! Refactored method call transpilation with reduced complexity
2
//! Original complexity: 58, Target: <20 per function
3
4
use crate::backend::Transpiler;
5
use crate::frontend::ast::Expr;
6
use anyhow::{bail, Result};
7
use proc_macro2::TokenStream;
8
use quote::{quote, format_ident};
9
10
impl Transpiler {
11
    /// Main dispatcher for method calls (complexity: ~15)
12
22
    pub fn transpile_method_call_refactored(
13
22
        &self,
14
22
        object: &Expr,
15
22
        method: &str,
16
22
        args: &[Expr],
17
22
    ) -> Result<TokenStream> {
18
22
        let obj_tokens = self.transpile_expr(object)
?0
;
19
22
        let arg_tokens: Result<Vec<_>> = args.iter().map(|a| 
self16
.
transpile_expr16
(
a16
)).collect();
20
22
        let arg_tokens = arg_tokens
?0
;
21
22
        // Dispatch to specialized handlers based on method category
23
22
        match method {
24
            // Iterator methods
25
22
            "map" | 
"filter"21
|
"reduce"20
|
"fold"19
|
"any"19
|
"all"18
|
"find"17
=>
26
6
                self.transpile_iterator_method(&obj_tokens, method, &arg_tokens),
27
            
28
            // HashMap/Dict methods
29
16
            "get" | 
"contains_key"15
|
"keys"14
|
"values"14
|
"items"14
|
"entry"13
=>
30
3
                self.transpile_hashmap_method(&obj_tokens, method, &arg_tokens),
31
            
32
            // HashSet methods
33
13
            "contains" | 
"union"12
|
"intersection"11
|
"difference"11
|
"symmetric_difference"11
=>
34
2
                self.transpile_hashset_method(&obj_tokens, method, &arg_tokens),
35
            
36
            // Collection mutators
37
11
            "insert" | "remove" | "clear" | "push" | 
"pop"10
|
"append"9
|
"extend"9
=>
38
2
                self.transpile_collection_mutator(&obj_tokens, method, &arg_tokens),
39
            
40
            // Collection accessors
41
9
            "len" | 
"is_empty"8
|
"iter"7
|
"slice"7
|
"first"7
|
"last"7
=>
42
2
                self.transpile_collection_accessor(&obj_tokens, method, &arg_tokens),
43
            
44
            // String methods
45
7
            "to_s" | "to_string" | "to_upper" | 
"to_lower"6
|
"length"6
|
46
6
            "trim" | 
"split"5
|
"replace"4
|
"starts_with"3
|
"ends_with"3
=>
47
4
                self.transpile_string_method(&obj_tokens, method, &arg_tokens),
48
            
49
            // DataFrame methods
50
3
            "select" | "groupby" | "agg" | "sort" | "mean" | "std" | "min" | "max" |
51
3
            "sum" | "count" | "drop_nulls" | "fill_null" | "pivot" | "melt" | 
52
3
            "head" | "tail" | "sample" | "describe" =>
53
0
                self.transpile_dataframe_method_refactored(&obj_tokens, method, &arg_tokens),
54
            
55
            // Default: pass through
56
            _ => {
57
3
                let method_ident = format_ident!("{}", method);
58
3
                Ok(quote! { #obj_tokens.#method_ident(#(#arg_tokens),*) })
59
            }
60
        }
61
22
    }
62
    
63
    /// Handle iterator methods (complexity: ~10)
64
6
    fn transpile_iterator_method(
65
6
        &self,
66
6
        obj: &TokenStream,
67
6
        method: &str,
68
6
        args: &[TokenStream],
69
6
    ) -> Result<TokenStream> {
70
6
        match method {
71
6
            "map" => Ok(
quote!1
{ #obj.iter().map(#(#args),*).collect::<Vec<_>>() }),
72
5
            "filter" => Ok(
quote!1
{ #obj.into_iter().filter(#(#args),*).collect::<Vec<_>>() }),
73
4
            "reduce" => Ok(
quote!1
{ #obj.into_iter().reduce(#(#args),*) }),
74
3
            "fold" => {
75
0
                if args.len() != 2 {
76
0
                    bail!("fold requires exactly 2 arguments");
77
0
                }
78
0
                let init = &args[0];
79
0
                let func = &args[1];
80
0
                Ok(quote! { #obj.into_iter().fold(#init, #func) })
81
            }
82
3
            "any" => Ok(
quote!1
{ #obj.iter().any(#(#args),*) }),
83
2
            "all" => Ok(
quote!1
{ #obj.iter().all(#(#args),*) }),
84
1
            "find" => Ok(quote! { #obj.iter().find(#(#args),*).cloned() }),
85
0
            _ => unreachable!("Unknown iterator method: {}", method),
86
        }
87
6
    }
88
    
89
    /// Handle HashMap/Dict methods (complexity: ~10)
90
3
    fn transpile_hashmap_method(
91
3
        &self,
92
3
        obj: &TokenStream,
93
3
        method: &str,
94
3
        args: &[TokenStream],
95
3
    ) -> Result<TokenStream> {
96
3
        let method_ident = format_ident!("{}", method);
97
3
        match method {
98
3
            "get" => Ok(
quote!1
{ #obj.#method_ident(#(#args),*).cloned() }),
99
2
            "items" => 
Ok(quote! { #obj.iter().map(|(k, v)| (k.clone(), v.clone())) })1
,
100
1
            "contains_key" | 
"keys"0
|
"values"0
|
"entry"0
=>
101
1
                Ok(quote! { #obj.#method_ident(#(#args),*) }),
102
0
            _ => unreachable!("Unknown HashMap method: {}", method),
103
        }
104
3
    }
105
    
106
    /// Handle `HashSet` methods (complexity: ~12)
107
2
    fn transpile_hashset_method(
108
2
        &self,
109
2
        obj: &TokenStream,
110
2
        method: &str,
111
2
        args: &[TokenStream],
112
2
    ) -> Result<TokenStream> {
113
2
        match method {
114
2
            "contains" => {
115
1
                let method_ident = format_ident!("{}", method);
116
1
                Ok(quote! { #obj.#method_ident(#(#args),*) })
117
            }
118
1
            "union" | 
"intersection"0
|
"difference"0
|
"symmetric_difference"0
=> {
119
1
                if args.len() != 1 {
120
0
                    bail!("{} requires exactly 1 argument", method);
121
1
                }
122
1
                let other = &args[0];
123
1
                let method_ident = format_ident!("{}", method);
124
1
                Ok(quote! { 
125
1
                    {
126
1
                        use std::collections::HashSet;
127
1
                        #obj.#method_ident(&#other).cloned().collect::<HashSet<_>>()
128
1
                    }
129
1
                })
130
            }
131
0
            _ => unreachable!("Unknown HashSet method: {}", method),
132
        }
133
2
    }
134
    
135
    /// Handle collection mutator methods (complexity: ~5)
136
2
    fn transpile_collection_mutator(
137
2
        &self,
138
2
        obj: &TokenStream,
139
2
        method: &str,
140
2
        args: &[TokenStream],
141
2
    ) -> Result<TokenStream> {
142
2
        let method_ident = format_ident!("{}", method);
143
2
        Ok(quote! { #obj.#method_ident(#(#args),*) })
144
2
    }
145
    
146
    /// Handle collection accessor methods (complexity: ~10)
147
2
    fn transpile_collection_accessor(
148
2
        &self,
149
2
        obj: &TokenStream,
150
2
        method: &str,
151
2
        args: &[TokenStream],
152
2
    ) -> Result<TokenStream> {
153
2
        match method {
154
2
            "slice" => {
155
0
                if args.len() != 2 {
156
0
                    bail!("slice requires exactly 2 arguments");
157
0
                }
158
0
                let start = &args[0];
159
0
                let end = &args[1];
160
0
                Ok(quote! { #obj[#start..#end].to_vec() })
161
            }
162
2
            "first" => 
Ok(quote! { #obj.first().cloned() })0
,
163
2
            "last" => 
Ok(quote! { #obj.last().cloned() })0
,
164
            _ => {
165
2
                let method_ident = format_ident!("{}", method);
166
2
                Ok(quote! { #obj.#method_ident(#(#args),*) })
167
            }
168
        }
169
2
    }
170
    
171
    /// Handle string methods (complexity: ~12)
172
4
    fn transpile_string_method(
173
4
        &self,
174
4
        obj: &TokenStream,
175
4
        method: &str,
176
4
        args: &[TokenStream],
177
4
    ) -> Result<TokenStream> {
178
4
        match method {
179
4
            "to_s" | "to_string" => 
Ok(quote! { #obj })0
,
180
4
            "to_upper" => Ok(
quote!1
{ #obj.to_uppercase(#(#args),*) }),
181
3
            "to_lower" => Ok(
quote!0
{ #obj.to_lowercase(#(#args),*) }),
182
3
            "length" => Ok(
quote!0
{ #obj.len(#(#args),*) }),
183
3
            "trim" => Ok(
quote!1
{ #obj.trim(#(#args),*).to_string() }),
184
2
            "split" => {
185
1
                if args.is_empty() {
186
0
                    Ok(quote! { #obj.split_whitespace().map(String::from).collect::<Vec<_>>() })
187
                } else {
188
1
                    Ok(quote! { #obj.split(#(#args),*).map(String::from).collect::<Vec<_>>() })
189
                }
190
            }
191
1
            "replace" => {
192
1
                if args.len() != 2 {
193
0
                    bail!("replace requires exactly 2 arguments");
194
1
                }
195
1
                Ok(quote! { #obj.replace(#(#args),*) })
196
            }
197
0
            "starts_with" | "ends_with" => {
198
0
                let method_ident = format_ident!("{}", method);
199
0
                Ok(quote! { #obj.#method_ident(#(#args),*) })
200
            }
201
0
            _ => unreachable!("Unknown string method: {}", method),
202
        }
203
4
    }
204
    
205
    /// Handle `DataFrame` methods (complexity: ~5)
206
0
    fn transpile_dataframe_method_refactored(
207
0
        &self,
208
0
        obj: &TokenStream,
209
0
        method: &str,
210
0
        args: &[TokenStream],
211
0
    ) -> Result<TokenStream> {
212
0
        let method_ident = format_ident!("{}", method);
213
0
        Ok(quote! { #obj.#method_ident(#(#args),*) })
214
0
    }
215
}
216
#[cfg(test)]
217
#[path = "method_call_refactored_tests.rs"]
218
mod tests;