baobao_codegen_typescript/ast/
consts.rs1use baobao_codegen::builder::{CodeBuilder, CodeFragment, Renderable};
4
5#[derive(Debug, Clone)]
7pub struct Const {
8 name: String,
9 value: String,
10 ty: Option<String>,
11 exported: bool,
12}
13
14impl Const {
15 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
16 Self {
17 name: name.into(),
18 value: value.into(),
19 ty: None,
20 exported: true,
21 }
22 }
23
24 pub fn ty(mut self, ty: impl Into<String>) -> Self {
26 self.ty = Some(ty.into());
27 self
28 }
29
30 pub fn private(mut self) -> Self {
32 self.exported = false;
33 self
34 }
35
36 pub fn render(&self, builder: CodeBuilder) -> CodeBuilder {
38 let export = if self.exported { "export " } else { "" };
39
40 let type_annotation = match &self.ty {
41 Some(ty) => format!(": {}", ty),
42 None => String::new(),
43 };
44
45 if self.value.contains('\n') {
47 let mut lines = self.value.lines();
48 let first = lines.next().unwrap_or("");
49 let builder = builder.line(&format!(
50 "{}const {}{} = {}",
51 export, self.name, type_annotation, first
52 ));
53
54 lines.fold(builder, |b, line| b.line(line))
55 } else {
56 builder.line(&format!(
57 "{}const {}{} = {};",
58 export, self.name, type_annotation, self.value
59 ))
60 }
61 }
62
63 pub fn build(&self) -> String {
65 self.render(CodeBuilder::typescript()).build()
66 }
67}
68
69impl Renderable for Const {
70 fn to_fragments(&self) -> Vec<CodeFragment> {
71 let export = if self.exported { "export " } else { "" };
72 let type_annotation = match &self.ty {
73 Some(ty) => format!(": {}", ty),
74 None => String::new(),
75 };
76
77 if self.value.contains('\n') {
79 let mut fragments = Vec::new();
80 let mut lines = self.value.lines();
81 let first = lines.next().unwrap_or("");
82 fragments.push(CodeFragment::Line(format!(
83 "{}const {}{} = {}",
84 export, self.name, type_annotation, first
85 )));
86 for line in lines {
87 fragments.push(CodeFragment::Line(line.to_string()));
88 }
89 fragments
90 } else {
91 vec![CodeFragment::Line(format!(
92 "{}const {}{} = {};",
93 export, self.name, type_annotation, self.value
94 ))]
95 }
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn test_simple_const() {
105 let c = Const::new("foo", "42").build();
106 assert_eq!(c, "export const foo = 42;\n");
107 }
108
109 #[test]
110 fn test_const_with_type() {
111 let c = Const::new("name", "\"hello\"").ty("string").build();
112 assert_eq!(c, "export const name: string = \"hello\";\n");
113 }
114
115 #[test]
116 fn test_private_const() {
117 let c = Const::new("secret", "123").private().build();
118 assert_eq!(c, "const secret = 123;\n");
119 }
120
121 #[test]
122 fn test_const_with_object() {
123 let c = Const::new("config", "{ debug: true }").build();
124 assert_eq!(c, "export const config = { debug: true };\n");
125 }
126}