TypeScript_Rust_Compiler/
types.rs

1//! Type mapping from TypeScript to Rust
2
3use crate::ast::*;
4use crate::error::Result;
5use std::collections::HashMap;
6
7/// Type mapper for converting TypeScript types to Rust types
8pub struct TypeMapper {
9    /// Mapping of TypeScript types to Rust types
10    type_mappings: HashMap<String, String>,
11    /// Generic type parameters
12    generics: Vec<String>,
13    /// Runtime support enabled
14    runtime: bool,
15}
16
17/// Extract struct name from generated code
18fn extract_struct_name(code: &str) -> String {
19    if let Some(start) = code.find("struct ") {
20        if let Some(end) = code[start + 7..].find(" {") {
21            return code[start + 7..start + 7 + end].to_string();
22        }
23    }
24    "Unknown".to_string()
25}
26
27impl TypeMapper {
28    /// Create a new type mapper
29    pub fn new(runtime: bool) -> Self {
30        let mut type_mappings = HashMap::new();
31
32        // Primitive type mappings
33        type_mappings.insert("string".to_string(), "String".to_string());
34        type_mappings.insert("number".to_string(), "f64".to_string());
35        type_mappings.insert("boolean".to_string(), "bool".to_string());
36        type_mappings.insert("void".to_string(), "()".to_string());
37        type_mappings.insert("never".to_string(), "!".to_string());
38        type_mappings.insert("any".to_string(), "Box<dyn Any>".to_string());
39        type_mappings.insert("unknown".to_string(), "Box<dyn Any>".to_string());
40        type_mappings.insert("null".to_string(), "Option<()>".to_string());
41        type_mappings.insert("undefined".to_string(), "Option<()>".to_string());
42        type_mappings.insert("object".to_string(), "Box<dyn Any>".to_string());
43        type_mappings.insert("symbol".to_string(), "Symbol".to_string());
44        type_mappings.insert("bigint".to_string(), "i64".to_string());
45
46        Self {
47            type_mappings,
48            generics: Vec::new(),
49            runtime,
50        }
51    }
52
53    /// Map a TypeScript type to Rust type
54    pub fn map_type(&mut self, ts_type: &Type) -> Result<String> {
55        match ts_type {
56            // Primitive types
57            Type::String => Ok("String".to_string()),
58            Type::Number => Ok("f64".to_string()),
59            Type::Boolean => Ok("bool".to_string()),
60            Type::Any => {
61                if self.runtime {
62                    Ok("Box<dyn Any>".to_string())
63                } else {
64                    Ok("serde_json::Value".to_string())
65                }
66            }
67            Type::Void => Ok("()".to_string()),
68            Type::Never => Ok("!".to_string()),
69            Type::Unknown => {
70                if self.runtime {
71                    Ok("Box<dyn Any>".to_string())
72                } else {
73                    Ok("serde_json::Value".to_string())
74                }
75            }
76            Type::Null => Ok("Option<()>".to_string()),
77            Type::Undefined => Ok("Option<()>".to_string()),
78            Type::Object => {
79                if self.runtime {
80                    Ok("Box<dyn Any>".to_string())
81                } else {
82                    Ok("serde_json::Value".to_string())
83                }
84            }
85            Type::Symbol => Ok("Symbol".to_string()),
86            Type::BigInt => Ok("i64".to_string()),
87
88            // Named types
89            Type::Named(name) => self.map_named_type(name),
90            Type::Qualified(qualified) => self.map_qualified_type(qualified),
91
92            // Generic types
93            Type::Generic(generic) => self.map_generic_type(generic),
94            Type::GenericNamed {
95                name,
96                type_arguments,
97            } => {
98                let rust_name = self.map_named_type(name)?;
99                if type_arguments.is_empty() {
100                    Ok(rust_name)
101                } else {
102                    let param_types: Result<Vec<String>> = type_arguments
103                        .iter()
104                        .map(|arg| self.map_type(arg))
105                        .collect();
106                    let param_types = param_types?;
107                    Ok(format!("{}<{}>", rust_name, param_types.join(", ")))
108                }
109            }
110            
111            // Union and intersection types
112            Type::Union { left, right } => {
113                let left_type = self.map_type(left)?;
114                let right_type = self.map_type(right)?;
115                Ok(format!("Union<{}, {}>", left_type, right_type))
116            }
117            Type::Intersection { left, right } => {
118                // For intersection types, we need to handle them differently
119                // since they can't be directly represented in Rust
120                let left_type = self.map_type(left)?;
121                let right_type = self.map_type(right)?;
122                
123                // Check if both types are object types
124                if left_type.starts_with("#[derive") && right_type.starts_with("#[derive") {
125                    // Extract struct names and create a combined type
126                    let left_struct = extract_struct_name(&left_type);
127                    let right_struct = extract_struct_name(&right_type);
128                    Ok(format!("{}And{}", left_struct, right_struct))
129                } else {
130                    Ok(format!("Intersection<{}, {}>", left_type, right_type))
131                }
132            }
133
134
135            // Array types
136            Type::Array(element_type) => {
137                let element_rust = self.map_type(element_type)?;
138                Ok(format!("Vec<{}>", element_rust))
139            }
140
141            // Tuple types
142            Type::Tuple(types) => self.map_tuple_type(types),
143
144            // Function types
145            Type::Function(func_type) => self.map_function_type(func_type),
146
147            // Object types
148            Type::ObjectType(obj_type) => self.map_object_type(obj_type),
149
150            // Index signatures
151            Type::IndexSignature(index_sig) => self.map_index_signature(index_sig),
152
153            // Mapped types
154            Type::Mapped(mapped) => self.map_mapped_type(mapped),
155
156            // Conditional types
157            Type::Conditional(conditional) => self.map_conditional_type(conditional),
158
159            // Template literal types
160            Type::TemplateLiteral(template) => self.map_template_literal_type(template),
161
162            // Parenthesized types
163            Type::Parenthesized(inner) => self.map_type(inner),
164
165            // Type queries
166            Type::TypeQuery(query) => self.map_type_query(query),
167
168            // Import types
169            Type::Import(import) => self.map_import_type(import),
170        }
171    }
172
173    /// Map named type
174    fn map_named_type(&self, name: &str) -> Result<String> {
175        if let Some(mapped) = self.type_mappings.get(name) {
176            Ok(mapped.clone())
177        } else {
178            // Convert to PascalCase for Rust structs/traits
179            Ok(self.to_pascal_case(name))
180        }
181    }
182
183    /// Map qualified type
184    fn map_qualified_type(&mut self, qualified: &QualifiedTypeName) -> Result<String> {
185        let left = self.map_type(&qualified.left)?;
186        Ok(format!("{}::{}", left, qualified.right))
187    }
188
189    /// Map generic type
190    fn map_generic_type(&mut self, generic: &GenericType) -> Result<String> {
191        let base_type = self.map_type(&generic.type_)?;
192        let type_args: Result<Vec<String>> = generic
193            .type_arguments
194            .iter()
195            .map(|t| self.map_type(t))
196            .collect();
197        let type_args = type_args?;
198
199        if type_args.is_empty() {
200            Ok(base_type)
201        } else {
202            // Handle special generic types
203            match base_type.as_str() {
204                "Array" => {
205                    if type_args.len() == 1 {
206                        Ok(format!("Vec<{}>", type_args[0]))
207                    } else {
208                        Ok(format!("Vec<{}>", type_args.join(", ")))
209                    }
210                }
211                "Promise" => {
212                    if type_args.len() == 1 {
213                        Ok(format!("std::pin::Pin<Box<dyn std::future::Future<Output = {}>>>", type_args[0]))
214                    } else {
215                        Ok("Box<dyn std::future::Future<Output = ()>>".to_string())
216                    }
217                }
218                "Map" | "Record" => {
219                    if type_args.len() == 2 {
220                        Ok(format!("std::collections::HashMap<{}, {}>", type_args[0], type_args[1]))
221                    } else {
222                        Ok("std::collections::HashMap<Box<dyn Any>, Box<dyn Any>>".to_string())
223                    }
224                }
225                "Set" => {
226                    if type_args.len() == 1 {
227                        Ok(format!("std::collections::HashSet<{}>", type_args[0]))
228                    } else {
229                        Ok("std::collections::HashSet<Box<dyn Any>>".to_string())
230                    }
231                }
232                "Partial" | "Required" | "Readonly" | "Pick" | "Omit" => {
233                    // These are complex type transformations that require runtime support
234                    if self.runtime {
235                        Ok("Box<dyn Any>".to_string())
236                    } else {
237                        Ok(base_type)
238                    }
239                }
240                _ => {
241                    Ok(format!("{}<{}>", base_type, type_args.join(", ")))
242                }
243            }
244        }
245    }
246
247
248    /// Map tuple type
249    fn map_tuple_type(&mut self, types: &[Type]) -> Result<String> {
250        if types.is_empty() {
251            return Ok("()".to_string());
252        }
253
254        let rust_types: Result<Vec<String>> = types.iter().map(|t| self.map_type(t)).collect();
255        let rust_types = rust_types?;
256
257        Ok(format!("({})", rust_types.join(", ")))
258    }
259
260    /// Map function type
261    fn map_function_type(&mut self, func_type: &FunctionType) -> Result<String> {
262        let params: Result<Vec<String>> = func_type
263            .parameters
264            .iter()
265            .map(|param| {
266                let param_type = if let Some(ref t) = param.type_ {
267                    self.map_type(t)?
268                } else {
269                    "Box<dyn Any>".to_string()
270                };
271                Ok(format!("{}: {}", param.name, param_type))
272            })
273            .collect();
274        let params = params?;
275
276        let return_type = self.map_type(&func_type.return_type)?;
277
278        Ok(format!("fn({}) -> {}", params.join(", "), return_type))
279    }
280
281    /// Map object type
282    fn map_object_type(&mut self, obj_type: &ObjectType) -> Result<String> {
283        let mut struct_fields = Vec::new();
284
285        for member in &obj_type.members {
286            match member {
287                ObjectTypeMember::Property(prop) => {
288                    let field_type = if let Some(ref t) = prop.type_ {
289                        self.map_type(t)?
290                    } else {
291                        "Box<dyn Any>".to_string()
292                    };
293
294                    let field_name = if prop.optional {
295                        format!("{}: Option<{}>", prop.name, field_type)
296                    } else {
297                        format!("{}: {}", prop.name, field_type)
298                    };
299
300                    struct_fields.push(field_name);
301                }
302                ObjectTypeMember::Method(method) => {
303                    // Methods become associated functions
304                    let params: Result<Vec<String>> = method
305                        .parameters
306                        .iter()
307                        .map(|param| {
308                            let param_type = if let Some(ref t) = param.type_ {
309                                self.map_type(t)?
310                            } else {
311                                "Box<dyn Any>".to_string()
312                            };
313                            Ok(format!("{}: {}", param.name, param_type))
314                        })
315                        .collect();
316                    let params = params?;
317
318                    let return_type = if let Some(ref t) = method.return_type {
319                        self.map_type(t)?
320                    } else {
321                        "()".to_string()
322                    };
323
324                    struct_fields.push(format!(
325                        "fn {}({}) -> {}",
326                        method.name,
327                        params.join(", "),
328                        return_type
329                    ));
330                }
331                _ => {
332                    // Handle other member types as needed
333                }
334            }
335        }
336
337        // Generate a proper struct name for object types
338        let struct_name = format!("ObjectType_{}", struct_fields.len());
339        Ok(format!(
340            "#[derive(Debug, Clone, Serialize, Deserialize)]\npub struct {} {{\n    {}\n}}",
341            struct_name,
342            struct_fields.join(",\n    ")
343        ))
344    }
345
346    /// Map index signature
347    fn map_index_signature(&mut self, index_sig: &IndexSignature) -> Result<String> {
348        let key_type = self.map_type(
349            &index_sig
350                .parameter
351                .type_
352                .as_ref()
353                .map_or(Type::String, |v| *v.clone()),
354        )?;
355        let value_type = self.map_type(&index_sig.type_)?;
356        Ok(format!("HashMap<{}, {}>", key_type, value_type))
357    }
358
359    /// Map mapped type
360    fn map_mapped_type(&mut self, mapped: &MappedType) -> Result<String> {
361        // Convert mapped type to generic struct
362        let key_type = self.map_type(
363            &mapped
364                .type_parameter
365                .constraint
366                .as_ref()
367                .map_or(Type::String, |v| *v.clone()),
368        )?;
369        let value_type = self.map_type(&mapped.type_)?;
370        Ok(format!("HashMap<{}, {}>", key_type, value_type))
371    }
372
373    /// Map conditional type
374    fn map_conditional_type(&mut self, conditional: &ConditionalType) -> Result<String> {
375        // Convert conditional type to trait with associated type
376        let check_type = self.map_type(&conditional.check_type)?;
377        let extends_type = self.map_type(&conditional.extends_type)?;
378        let _true_type = self.map_type(&conditional.true_type)?;
379        let _false_type = self.map_type(&conditional.false_type)?;
380
381        Ok(format!(
382            "trait ConditionalType {{\n    type Output: PartialEq<{}>;\n    fn condition<{}>() -> Self::Output;\n}}",
383            extends_type, check_type
384        ))
385    }
386
387    /// Map template literal type
388    fn map_template_literal_type(&mut self, template: &TemplateLiteralType) -> Result<String> {
389        // Convert template literal type to const generic or macro
390        Ok(format!("\"{}\"", template.head))
391    }
392
393    /// Map type query
394    fn map_type_query(&mut self, _query: &TypeQuery) -> Result<String> {
395        // Convert type query to associated type
396        Ok("TypeQuery".to_string())
397    }
398
399    /// Map import type
400    fn map_import_type(&mut self, import: &ImportType) -> Result<String> {
401        let base_type = self.map_type(&import.argument)?;
402        if let Some(ref qualifier) = import.qualifier {
403            Ok(format!("{}::{}", base_type, qualifier))
404        } else {
405            Ok(base_type)
406        }
407    }
408
409    /// Convert string to PascalCase
410    fn to_pascal_case(&self, s: &str) -> String {
411        let mut result = String::new();
412        let mut capitalize = true;
413
414        for ch in s.chars() {
415            if ch == '_' || ch == '-' {
416                capitalize = true;
417            } else if capitalize {
418                result.push(ch.to_uppercase().next().unwrap_or(ch));
419                capitalize = false;
420            } else {
421                result.push(ch);
422            }
423        }
424
425        result
426    }
427
428    /// Add generic type parameter
429    pub fn add_generic(&mut self, name: String) {
430        self.generics.push(name);
431    }
432
433    /// Get all generic type parameters
434    pub fn get_generics(&self) -> &[String] {
435        &self.generics
436    }
437
438    /// Clear generic type parameters
439    pub fn clear_generics(&mut self) {
440        self.generics.clear();
441    }
442}
443
444/// Type mapping utilities
445pub struct TypeMappingUtils;
446
447impl TypeMappingUtils {
448    /// Check if a TypeScript type is primitive
449    pub fn is_primitive(ts_type: &Type) -> bool {
450        matches!(
451            ts_type,
452            Type::String
453                | Type::Number
454                | Type::Boolean
455                | Type::Void
456                | Type::Never
457                | Type::Any
458                | Type::Unknown
459                | Type::Null
460                | Type::Undefined
461                | Type::Object
462                | Type::Symbol
463                | Type::BigInt
464        )
465    }
466
467    /// Check if a TypeScript type is nullable
468    pub fn is_nullable(ts_type: &Type) -> bool {
469        matches!(ts_type, Type::Null | Type::Undefined)
470    }
471
472    /// Check if a TypeScript type is optional
473    pub fn is_optional(_ts_type: &Type) -> bool {
474        // This would need to be determined from context
475        false
476    }
477
478    /// Get the underlying type for optional types
479    pub fn get_underlying_type(ts_type: &Type) -> &Type {
480        // This would need to be implemented based on the specific type
481        ts_type
482    }
483
484    /// Check if a TypeScript type needs runtime support
485    pub fn needs_runtime(ts_type: &Type) -> bool {
486        matches!(
487            ts_type,
488            Type::Any | Type::Unknown | Type::Object | Type::Union { .. } | Type::Intersection { .. }
489        )
490    }
491
492    /// Generate Rust imports for a type
493    pub fn generate_imports(ts_type: &Type) -> Vec<String> {
494        let mut imports = Vec::new();
495
496        match ts_type {
497            Type::Any | Type::Unknown | Type::Object => {
498                imports.push("use std::any::Any;".to_string());
499                imports.push("use std::boxed::Box;".to_string());
500            }
501            Type::Union { .. } => {
502                imports.push("use serde::{Deserialize, Serialize};".to_string());
503            }
504            Type::Intersection { .. } => {
505                imports.push("use std::ops::Add;".to_string());
506            }
507            Type::Array(_) => {
508                imports.push("use std::vec::Vec;".to_string());
509            }
510            Type::Tuple(_) => {
511                // Tuples don't need special imports
512            }
513            Type::Function(_) => {
514                imports.push("use std::boxed::Box;".to_string());
515            }
516            Type::Null => {
517                // No specific import needed for Null (unit type)
518            }
519            _ => {}
520        }
521
522        imports
523    }
524}