1use std::fmt::Display;
2
3#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4pub enum Member {
5    Literal(String),
6    Ident(String),
7}
8
9impl Display for Member {
10    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11        match self {
12            Self::Literal(lit) => f.write_str(&format!(
13                r#""{}""#,
14                lit.trim_start_matches('"').trim_end_matches('"')
15            )),
16            Self::Ident(ident) => f.write_str(ident),
17        }
18    }
19}
20
21#[derive(Debug, Clone, PartialEq, Eq, Hash)]
22pub enum TagType {
23    Toc(String),
27    Module(String, Option<String>),
31    Divider(char),
35    Func(String, Op),
40    Expr(String, Op),
45    Export(String),
51    BriefStart,
55    BriefEnd,
59    Param(Name, Ty, Option<String>),
63    Return(Ty, Option<String>, Option<String>),
67    Class(String, Option<String>),
71    Field(Scope, Name, Ty, Option<String>),
75    Alias(String, Option<Ty>),
83    Variant(Member, Option<String>),
91    Type(Ty, Option<String>),
95    Tag(String),
99    See(String),
103    Usage(Option<String>, String),
107    UsageStart(Option<String>),
111    UsageEnd,
115    Comment(String),
119    Skip,
121}
122
123#[derive(Debug, Clone, PartialEq, Eq, Hash)]
124pub enum Op {
125    Deep(Vec<Op>),
126    Dot(String),
127    Colon(String),
128}
129
130impl Display for Op {
131    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132        match self {
133            Self::Deep(mixed) => {
134                for mix in mixed {
135                    mix.fmt(f)?;
136                }
137                Ok(())
138            }
139            Self::Dot(dot) => {
140                f.write_str(".")?;
141                f.write_str(dot)
142            }
143            Self::Colon(colon) => {
144                f.write_str(":")?;
145                f.write_str(colon)
146            }
147        }
148    }
149}
150
151#[derive(Debug, Clone, PartialEq, Eq, Hash)]
152pub enum Scope {
153    Public,
154    Private,
155    Protected,
156    Package,
157}
158
159#[derive(Debug, Clone, PartialEq, Eq, Hash)]
160pub enum Name {
161    Req(String),
162    Opt(String),
163}
164
165impl Display for Name {
166    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167        match self {
168            Self::Req(n) => f.write_str(n),
169            Self::Opt(n) => {
170                f.write_str(n)?;
171                f.write_str("?")
172            }
173        }
174    }
175}
176
177#[derive(Debug, Clone, PartialEq, Eq, Hash)]
179pub enum Ty {
180    Nil,
181    Any,
182    Unknown,
183    Boolean,
184    String,
185    Number,
186    Integer,
187    Function,
188    Thread,
189    Userdata,
190    Lightuserdata,
191    Ref(String),
192    Member(Member),
193    Array(Box<Ty>),
194    Table(Option<(Box<Ty>, Box<Ty>)>),
195    Fun(Vec<(Name, Ty)>, Option<Vec<Ty>>),
196    Dict(Vec<(Name, Ty)>),
197    Union(Box<Ty>, Box<Ty>),
198}
199
200impl Display for Ty {
201    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202        fn list_like(args: &[(Name, Ty)]) -> String {
203            args.iter()
204                .map(|(n, t)| format!("{n}:{t}"))
205                .collect::<Vec<String>>()
206                .join(",")
207        }
208
209        match self {
210            Self::Nil => f.write_str("nil"),
211            Self::Any => f.write_str("any"),
212            Self::Unknown => f.write_str("unknown"),
213            Self::Boolean => f.write_str("boolean"),
214            Self::String => f.write_str("string"),
215            Self::Number => f.write_str("number"),
216            Self::Integer => f.write_str("integer"),
217            Self::Function => f.write_str("function"),
218            Self::Thread => f.write_str("thread"),
219            Self::Userdata => f.write_str("userdata"),
220            Self::Lightuserdata => f.write_str("lightuserdata"),
221            Self::Ref(id) => f.write_str(id),
222            Self::Array(ty) => {
223                f.write_str(&ty.to_string())?;
224                f.write_str("[]")
225            }
226            Self::Table(kv) => match kv {
227                Some((k, v)) => {
228                    f.write_str("table<")?;
229                    f.write_str(&k.to_string())?;
230                    f.write_str(",")?;
231                    f.write_str(&v.to_string())?;
232                    f.write_str(">")
233                }
234                None => f.write_str("table"),
235            },
236            Self::Fun(args, ret) => {
237                f.write_str("fun(")?;
238                f.write_str(&list_like(args))?;
239                f.write_str(")")?;
240                if let Some(ret) = ret {
241                    f.write_str(":")?;
242                    f.write_str(
243                        &ret.iter()
244                            .map(|r| r.to_string())
245                            .collect::<Vec<String>>()
246                            .join(","),
247                    )?;
248                }
249                Ok(())
250            }
251            Self::Dict(kv) => {
252                f.write_str("{")?;
253                f.write_str(&list_like(kv))?;
254                f.write_str("}")
255            }
256            Self::Union(rhs, lhs) => {
257                f.write_str(&rhs.to_string())?;
258                f.write_str("|")?;
259                f.write_str(&lhs.to_string())
260            }
261            Self::Member(mem) => mem.fmt(f),
262        }
263    }
264}