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