use std::fmt::Display;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Member {
Literal(String),
Ident(String),
}
impl Display for Member {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Literal(lit) => f.write_str(&format!(
r#""{}""#,
lit.trim_start_matches('"').trim_end_matches('"')
)),
Self::Ident(ident) => f.write_str(ident),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum TagType {
Toc(String),
Module(String, Option<String>),
Divider(char),
Func(String, Op),
Expr(String, Op),
Export(String),
BriefStart,
BriefEnd,
Param(Name, Ty, Option<String>),
Return(Ty, Option<String>, Option<String>),
Class(String, Option<String>),
Field(Scope, Name, Ty, Option<String>),
Variable(String),
Enum(String),
Alias(String, Option<Ty>),
Variant(Member, Option<String>),
Type(Ty, Option<String>),
Tag(String),
See(String),
Usage(Option<String>, String),
UsageStart(Option<String>),
UsageEnd,
Comment(String),
Skip,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Op {
Deep(Vec<Op>),
Dot(String),
Colon(String),
}
impl Display for Op {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Deep(mixed) => {
for mix in mixed {
mix.fmt(f)?;
}
Ok(())
}
Self::Dot(dot) => {
f.write_str(".")?;
f.write_str(dot)
}
Self::Colon(colon) => {
f.write_str(":")?;
f.write_str(colon)
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Scope {
Public,
Private,
Protected,
Package,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Name {
Req(String),
Opt(String),
}
impl Display for Name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Req(n) => f.write_str(n),
Self::Opt(n) => {
f.write_str(n)?;
f.write_str("?")
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Ty {
Nil,
Any,
Unknown,
Boolean,
String,
Number,
Integer,
Function,
Thread,
Userdata,
Lightuserdata,
Ref(String),
Member(Member),
Array(Box<Ty>),
Table(Option<(Box<Ty>, Box<Ty>)>),
Fun(Vec<(Name, Ty)>, Option<Vec<Ty>>),
Dict(Vec<(Name, Ty)>),
Union(Box<Ty>, Box<Ty>),
}
impl Display for Ty {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn list_like(args: &[(Name, Ty)]) -> String {
args.iter()
.map(|(n, t)| format!("{n}:{t}"))
.collect::<Vec<String>>()
.join(",")
}
match self {
Self::Nil => f.write_str("nil"),
Self::Any => f.write_str("any"),
Self::Unknown => f.write_str("unknown"),
Self::Boolean => f.write_str("boolean"),
Self::String => f.write_str("string"),
Self::Number => f.write_str("number"),
Self::Integer => f.write_str("integer"),
Self::Function => f.write_str("function"),
Self::Thread => f.write_str("thread"),
Self::Userdata => f.write_str("userdata"),
Self::Lightuserdata => f.write_str("lightuserdata"),
Self::Ref(id) => f.write_str(id),
Self::Array(ty) => {
f.write_str(&ty.to_string())?;
f.write_str("[]")
}
Self::Table(kv) => match kv {
Some((k, v)) => {
f.write_str("table<")?;
f.write_str(&k.to_string())?;
f.write_str(",")?;
f.write_str(&v.to_string())?;
f.write_str(">")
}
None => f.write_str("table"),
},
Self::Fun(args, ret) => {
f.write_str("fun(")?;
f.write_str(&list_like(args))?;
f.write_str(")")?;
if let Some(ret) = ret {
f.write_str(":")?;
f.write_str(
&ret.iter()
.map(|r| r.to_string())
.collect::<Vec<String>>()
.join(","),
)?;
}
Ok(())
}
Self::Dict(kv) => {
f.write_str("{")?;
f.write_str(&list_like(kv))?;
f.write_str("}")
}
Self::Union(rhs, lhs) => {
f.write_str(&rhs.to_string())?;
f.write_str("|")?;
f.write_str(&lhs.to_string())
}
Self::Member(mem) => mem.fmt(f),
}
}
}