libmoonwave/tags/
param.rs

1use serde::Serialize;
2
3use crate::{diagnostic::Diagnostic, span::Span};
4
5#[derive(Debug, PartialEq, Serialize, Clone)]
6pub struct ParamTag<'a> {
7    pub name: Span<'a>,
8    pub desc: Span<'a>,
9    pub lua_type: Span<'a>,
10    #[serde(skip)]
11    pub source: Span<'a>,
12}
13
14impl<'a> ParamTag<'a> {
15    pub fn parse(span: Span<'a>) -> Result<Self, Diagnostic> {
16        let mut pieces = span.splitn(2, "--");
17        let name_and_maybe_type: Span<'_> = pieces.next().unwrap().trim();
18        let desc = pieces
19            .next()
20            .map(|desc| desc.trim())
21            .unwrap_or_else(|| Span::empty(span.file_id));
22
23        let mut pieces = name_and_maybe_type.splitn(2, " ");
24        let name = pieces.next().unwrap().trim();
25
26        if name.is_empty() {
27            return Err(span.diagnostic("Param name is required"));
28        }
29
30        let lua_type = pieces
31            .next()
32            .map(|name| name.trim())
33            .unwrap_or_else(|| Span::dummy(""));
34
35        Ok(Self {
36            name,
37            desc,
38            lua_type,
39            source: span,
40        })
41    }
42}
43
44#[cfg(test)]
45mod test {
46    use insta::assert_yaml_snapshot;
47
48    use super::*;
49
50    #[test]
51    fn everything_sandwich() {
52        let source = Span::dummy("COOL_NAME foo -- HEY! This is a sweet description");
53
54        let value = ParamTag::parse(source).unwrap();
55        assert_yaml_snapshot!(value, @r###"
56        ---
57        name: COOL_NAME
58        desc: HEY! This is a sweet description
59        lua_type: foo
60        "###);
61    }
62
63    #[test]
64    fn lovecraftian_type() {
65        let source = Span::dummy("foo Roact.Element<{ oh_no: string -> coroutine }> -- I'm sorry.");
66        let value = ParamTag::parse(source).unwrap();
67        assert_yaml_snapshot!(value, @r###"
68        ---
69        name: foo
70        desc: "I'm sorry."
71        lua_type: "Roact.Element<{ oh_no: string -> coroutine }>"
72        "###);
73    }
74
75    #[test]
76    fn no_description() {
77        let source = Span::dummy("coffee tasty");
78        let value = ParamTag::parse(source).unwrap();
79        assert_yaml_snapshot!(value, @r###"
80        ---
81        name: coffee
82        desc: ""
83        lua_type: tasty
84        "###);
85    }
86}