kotlin_poet_rs/spec/
file.rs1use crate::io::RenderKotlin;
2use crate::spec::{Annotation, AnnotationTarget, Class, ClassLikeTypeName, CodeBlock, Comment, Function, Import, Package, Property, TypeAlias};
3use crate::tokens;
4
5#[derive(Debug, Clone)]
6enum KotlinFileNode {
7 Property(Property),
8 Function(Function),
9 TypeAlias(TypeAlias),
10 Class(Class),
11}
12
13#[derive(Debug, Clone)]
15pub struct KotlinFile {
16 package: Option<Package>,
17 imports: Vec<Import>,
18 nodes: Vec<KotlinFileNode>,
19 annotations: Vec<Annotation>,
20 header_comments: Vec<Comment>,
21}
22
23impl KotlinFile {
24 pub fn new<PackageLike: Into<Package>>(package: PackageLike) -> Self {
26 KotlinFile {
27 package: Some(package.into()),
28 imports: Vec::new(),
29 nodes: Vec::new(),
30 annotations: Vec::new(),
31 header_comments: Vec::new(),
32 }
33 }
34
35 pub fn root() -> Self {
37 KotlinFile {
38 package: None,
39 imports: Vec::new(),
40 nodes: Vec::new(),
41 annotations: Vec::new(),
42 header_comments: Vec::new(),
43 }
44 }
45
46 pub fn header_comment<CommentLike: Into<Comment>>(mut self, comment: CommentLike) -> Self {
51 self.header_comments.push(comment.into());
52 self
53 }
54
55 pub fn import(mut self, import: Import) -> Self {
57 self.imports.push(import);
58 self
59 }
60
61 pub fn property(mut self, property: Property) -> Self {
63 self.nodes.push(KotlinFileNode::Property(property));
64 self
65 }
66
67 pub fn function(mut self, function: Function) -> Self {
69 self.nodes.push(KotlinFileNode::Function(function));
70 self
71 }
72
73 pub fn type_alias(mut self, type_alias: TypeAlias) -> Self {
75 self.nodes.push(KotlinFileNode::TypeAlias(type_alias));
76 self
77 }
78
79 pub fn class(mut self, class: Class) -> Self {
81 self.nodes.push(KotlinFileNode::Class(class));
82 self
83 }
84
85 pub fn annotation(mut self, annotation: Annotation) -> Self {
88 self.annotations.push(
89 annotation
90 .target(AnnotationTarget::File)
91 );
92 self
93 }
94}
95
96impl From<ClassLikeTypeName> for KotlinFile {
97 fn from(value: ClassLikeTypeName) -> Self {
98 let package = value.package;
99 KotlinFile::new(package)
100 }
101}
102
103impl RenderKotlin for KotlinFile {
104 fn render_into(&self, block: &mut CodeBlock) {
105 if !self.header_comments.is_empty() {
106 for comment in &self.header_comments {
107 block.push_renderable(comment);
108 block.push_new_line();
109 }
110 block.push_new_line()
111 }
112
113 for annotation in &self.annotations {
114 block.push_renderable(annotation);
115 block.push_new_line();
116 }
117 if !self.annotations.is_empty() {
118 block.push_new_line();
119 }
120
121 if let Some(package) = &self.package {
122 block.push_static_atom(tokens::keyword::PACKAGE);
123 block.push_space();
124 block.push_renderable(package);
125 block.push_new_line();
126 }
127
128 for import in &self.imports {
129 block.push_renderable(import);
130 block.push_new_line();
131 }
132
133 for node in &self.nodes {
134 match node {
135 KotlinFileNode::Property(property) => {
136 block.push_new_line();
137 block.push_renderable(property);
138 block.push_new_line();
139 }
140 KotlinFileNode::Function(function) => {
141 block.push_new_line();
142 block.push_renderable(function);
143 block.push_new_line();
144 }
145 KotlinFileNode::TypeAlias(type_alias) => {
146 block.push_new_line();
147 block.push_renderable(type_alias);
148 block.push_new_line();
149 }
150 KotlinFileNode::Class(class) => {
151 block.push_new_line();
152 block.push_renderable(class);
153 block.push_new_line();
154 }
155 }
156 }
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use crate::spec::{Comment, Function, KotlinFile};
163 use crate::io::RenderKotlin;
164
165 #[test]
166 fn test_root_file() {
167 let file = KotlinFile::root()
168 .function(Function::new("main"));
169
170 assert_eq!(
171 file.render_string(),
172 "public fun main(): kotlin.Unit",
173 )
174 }
175
176 #[test]
177 fn test_file_with_header_comments() {
178 let file = KotlinFile::new("com.example")
179 .header_comment(Comment::from("This is a header comment"))
180 .header_comment(Comment::from("This is another header comment"));
181
182 assert_eq!(
183 file.render_string(),
184 "// This is a header comment\n// This is another header comment\n\npackage com.example"
185 )
186 }
187}