kotlin_poet_rs/spec/
import.rs

1use crate::io::RenderKotlin;
2use crate::spec::{ClassLikeTypeName, CodeBlock, Name, Package};
3use crate::tokens;
4
5/// Defines [Kotlin's import statement](https://kotlinlang.org/docs/packages.html#imports)
6#[derive(Debug, PartialEq, Clone)]
7pub enum Import {
8    /// Import a class-like type possibly aliased with a different name
9    ClassLikeType { type_name: ClassLikeTypeName, alias: Option<Name> },
10    /// Import of all types from a package
11    Projection(Package),
12    /// Import of function / property
13    TopLevel { package: Package, name: Name },
14}
15
16impl Import {
17    /// Creates an import statement for a class-like type
18    pub fn class_like<ClassLikeTypeNameLike: Into<ClassLikeTypeName>>(type_name: ClassLikeTypeNameLike) -> Self {
19        Import::ClassLikeType {
20            type_name: type_name.into(),
21            alias: None,
22        }
23    }
24
25    /// Creates an import statement for a class-like type with an alias
26    pub fn class_like_alias<NameLike: Into<Name>, ClassLikeTypeNameLike: Into<ClassLikeTypeName>>(type_name: ClassLikeTypeNameLike, alias: NameLike) -> Self {
27        Import::ClassLikeType {
28            type_name: type_name.into(),
29            alias: Some(alias.into()),
30        }
31    }
32
33    /// Creates an import statement for all types in a package
34    pub fn projection<PackageLike: Into<Package>>(package: PackageLike) -> Self {
35        Import::Projection(package.into())
36    }
37
38    /// Creates an import statement for a function or property
39    pub fn top_level<NameLike: Into<Name>, PackageLike: Into<Package>>(
40        package: PackageLike,
41        name: NameLike
42    ) -> Self {
43        Import::TopLevel {
44            package: package.into(),
45            name: name.into(),
46        }
47    }
48}
49
50impl RenderKotlin for Import {
51    fn render_into(&self, block: &mut CodeBlock) {
52        block.push_static_atom(tokens::keyword::IMPORT);
53        block.push_space();
54
55        match self {
56            Import::ClassLikeType { type_name, alias } => {
57                block.push_renderable(type_name);
58                if let Some(alias) = alias {
59                    block.push_space();
60                    block.push_static_atom(tokens::keyword::AS);
61                    block.push_space();
62                    block.push_renderable(alias);
63                }
64            }
65            Import::Projection(package) => {
66                block.push_renderable(package);
67                block.push_static_atom(tokens::DOT);
68                block.push_static_atom(tokens::STAR);
69            }
70            Import::TopLevel { package, name } => {
71                block.push_renderable(package);
72                block.push_static_atom(tokens::DOT);
73                block.push_renderable(name);
74            }
75        }
76
77        block.push_new_line();
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use std::str::FromStr;
84    use super::*;
85    use crate::spec::{ClassLikeTypeName, Name};
86
87    #[test]
88    fn test_import_class_like_type() {
89        let import = Import::class_like(
90            ClassLikeTypeName::from_str("com.example.Foo").unwrap()
91        );
92        assert_eq!(import.render_string(), "import com.example.Foo");
93    }
94
95    #[test]
96    fn test_import_class_like_type_with_alias() {
97        let import = Import::class_like_alias(
98            ClassLikeTypeName::top_level(
99                Package::from_str("com.example").unwrap(),
100                Name::from_str("Foo").unwrap(),
101            ),
102            Name::from("Bar"),
103        );
104        assert_eq!(import.render_string(), "import com.example.Foo as Bar");
105    }
106
107    #[test]
108    fn test_import_projection() {
109        let import = Import::Projection(Package::from_str("com.example").unwrap());
110        assert_eq!(import.render_string(), "import com.example.*");
111    }
112
113    #[test]
114    fn test_import_top_level() {
115        let import = Import::TopLevel {
116            package: Package::from_str("com.example").unwrap(),
117            name: Name::from_str("foo").unwrap(),
118        };
119        assert_eq!(import.render_string(), "import com.example.foo");
120    }
121}