Coverage Report

Created: 2025-09-08 21: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
0
    pub fn transpile_method_call_refactored(
13
0
        &self,
14
0
        object: &Expr,
15
0
        method: &str,
16
0
        args: &[Expr],
17
0
    ) -> Result<TokenStream> {
18
0
        let obj_tokens = self.transpile_expr(object)?;
19
0
        let arg_tokens: Result<Vec<_>> = args.iter().map(|a| self.transpile_expr(a)).collect();
20
0
        let arg_tokens = arg_tokens?;
21
22
        // Dispatch to specialized handlers based on method category
23
0
        match method {
24
            // Iterator methods
25
0
            "map" | "filter" | "reduce" | "fold" | "any" | "all" | "find" => 
26
0
                self.transpile_iterator_method(&obj_tokens, method, &arg_tokens),
27
            
28
            // HashMap/Dict methods
29
0
            "get" | "contains_key" | "keys" | "values" | "items" | "entry" =>
30
0
                self.transpile_hashmap_method(&obj_tokens, method, &arg_tokens),
31
            
32
            // HashSet methods
33
0
            "contains" | "union" | "intersection" | "difference" | "symmetric_difference" =>
34
0
                self.transpile_hashset_method(&obj_tokens, method, &arg_tokens),
35
            
36
            // Collection mutators
37
0
            "insert" | "remove" | "clear" | "push" | "pop" | "append" | "extend" =>
38
0
                self.transpile_collection_mutator(&obj_tokens, method, &arg_tokens),
39
            
40
            // Collection accessors
41
0
            "len" | "is_empty" | "iter" | "slice" | "first" | "last" =>
42
0
                self.transpile_collection_accessor(&obj_tokens, method, &arg_tokens),
43
            
44
            // String methods
45
0
            "to_s" | "to_string" | "to_upper" | "to_lower" | "length" | 
46
0
            "trim" | "split" | "replace" | "starts_with" | "ends_with" =>
47
0
                self.transpile_string_method(&obj_tokens, method, &arg_tokens),
48
            
49
            // DataFrame methods
50
0
            "select" | "groupby" | "agg" | "sort" | "mean" | "std" | "min" | "max" |
51
0
            "sum" | "count" | "drop_nulls" | "fill_null" | "pivot" | "melt" | 
52
0
            "head" | "tail" | "sample" | "describe" =>
53
0
                self.transpile_dataframe_method_refactored(&obj_tokens, method, &arg_tokens),
54
            
55
            // Default: pass through
56
            _ => {
57
0
                let method_ident = format_ident!("{}", method);
58
0
                Ok(quote! { #obj_tokens.#method_ident(#(#arg_tokens),*) })
59
            }
60
        }
61
0
    }
62
    
63
    /// Handle iterator methods (complexity: ~10)
64
0
    fn transpile_iterator_method(
65
0
        &self,
66
0
        obj: &TokenStream,
67
0
        method: &str,
68
0
        args: &[TokenStream],
69
0
    ) -> Result<TokenStream> {
70
0
        match method {
71
0
            "map" => Ok(quote! { #obj.iter().map(#(#args),*).collect::<Vec<_>>() }),
72
0
            "filter" => Ok(quote! { #obj.into_iter().filter(#(#args),*).collect::<Vec<_>>() }),
73
0
            "reduce" => Ok(quote! { #obj.into_iter().reduce(#(#args),*) }),
74
0
            "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
0
            "any" => Ok(quote! { #obj.iter().any(#(#args),*) }),
83
0
            "all" => Ok(quote! { #obj.iter().all(#(#args),*) }),
84
0
            "find" => Ok(quote! { #obj.iter().find(#(#args),*).cloned() }),
85
0
            _ => unreachable!("Unknown iterator method: {}", method),
86
        }
87
0
    }
88
    
89
    /// Handle HashMap/Dict methods (complexity: ~10)
90
0
    fn transpile_hashmap_method(
91
0
        &self,
92
0
        obj: &TokenStream,
93
0
        method: &str,
94
0
        args: &[TokenStream],
95
0
    ) -> Result<TokenStream> {
96
0
        let method_ident = format_ident!("{}", method);
97
0
        match method {
98
0
            "get" => Ok(quote! { #obj.#method_ident(#(#args),*).cloned() }),
99
0
            "items" => Ok(quote! { #obj.iter().map(|(k, v)| (k.clone(), v.clone())) }),
100
0
            "contains_key" | "keys" | "values" | "entry" => 
101
0
                Ok(quote! { #obj.#method_ident(#(#args),*) }),
102
0
            _ => unreachable!("Unknown HashMap method: {}", method),
103
        }
104
0
    }
105
    
106
    /// Handle `HashSet` methods (complexity: ~12)
107
0
    fn transpile_hashset_method(
108
0
        &self,
109
0
        obj: &TokenStream,
110
0
        method: &str,
111
0
        args: &[TokenStream],
112
0
    ) -> Result<TokenStream> {
113
0
        match method {
114
0
            "contains" => {
115
0
                let method_ident = format_ident!("{}", method);
116
0
                Ok(quote! { #obj.#method_ident(#(#args),*) })
117
            }
118
0
            "union" | "intersection" | "difference" | "symmetric_difference" => {
119
0
                if args.len() != 1 {
120
0
                    bail!("{} requires exactly 1 argument", method);
121
0
                }
122
0
                let other = &args[0];
123
0
                let method_ident = format_ident!("{}", method);
124
0
                Ok(quote! { 
125
0
                    {
126
0
                        use std::collections::HashSet;
127
0
                        #obj.#method_ident(&#other).cloned().collect::<HashSet<_>>()
128
0
                    }
129
0
                })
130
            }
131
0
            _ => unreachable!("Unknown HashSet method: {}", method),
132
        }
133
0
    }
134
    
135
    /// Handle collection mutator methods (complexity: ~5)
136
0
    fn transpile_collection_mutator(
137
0
        &self,
138
0
        obj: &TokenStream,
139
0
        method: &str,
140
0
        args: &[TokenStream],
141
0
    ) -> Result<TokenStream> {
142
0
        let method_ident = format_ident!("{}", method);
143
0
        Ok(quote! { #obj.#method_ident(#(#args),*) })
144
0
    }
145
    
146
    /// Handle collection accessor methods (complexity: ~10)
147
0
    fn transpile_collection_accessor(
148
0
        &self,
149
0
        obj: &TokenStream,
150
0
        method: &str,
151
0
        args: &[TokenStream],
152
0
    ) -> Result<TokenStream> {
153
0
        match method {
154
0
            "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
0
            "first" => Ok(quote! { #obj.first().cloned() }),
163
0
            "last" => Ok(quote! { #obj.last().cloned() }),
164
            _ => {
165
0
                let method_ident = format_ident!("{}", method);
166
0
                Ok(quote! { #obj.#method_ident(#(#args),*) })
167
            }
168
        }
169
0
    }
170
    
171
    /// Handle string methods (complexity: ~12)
172
0
    fn transpile_string_method(
173
0
        &self,
174
0
        obj: &TokenStream,
175
0
        method: &str,
176
0
        args: &[TokenStream],
177
0
    ) -> Result<TokenStream> {
178
0
        match method {
179
0
            "to_s" | "to_string" => Ok(quote! { #obj }),
180
0
            "to_upper" => Ok(quote! { #obj.to_uppercase(#(#args),*) }),
181
0
            "to_lower" => Ok(quote! { #obj.to_lowercase(#(#args),*) }),
182
0
            "length" => Ok(quote! { #obj.len(#(#args),*) }),
183
0
            "trim" => Ok(quote! { #obj.trim(#(#args),*).to_string() }),
184
0
            "split" => {
185
0
                if args.is_empty() {
186
0
                    Ok(quote! { #obj.split_whitespace().map(String::from).collect::<Vec<_>>() })
187
                } else {
188
0
                    Ok(quote! { #obj.split(#(#args),*).map(String::from).collect::<Vec<_>>() })
189
                }
190
            }
191
0
            "replace" => {
192
0
                if args.len() != 2 {
193
0
                    bail!("replace requires exactly 2 arguments");
194
0
                }
195
0
                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
0
    }
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;