px-wsdom-ts-parse 0.0.6

for the wsdom crate, and potentially other uses
Documentation
use winnow::{
    combinator::{alt, delimited, opt, preceded, separated0, separated_pair},
    PResult, Parser,
};

use super::{
    generic::GenericsDeclaration,
    ts_type::TsType,
    util::{token, token_word, word0, word1, Parsable},
};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Method<'a> {
    pub name: MethodName<'a>,
    pub generics: GenericsDeclaration<'a>,
    pub args: Vec<MethodArg<'a>>,
    pub ret: Option<TsType<'a>>,
    pub optional: bool,
    pub is_static: bool,
}
impl<'a> Parsable<'a> for Method<'a> {
    fn parse(input: &mut &'a str) -> PResult<Self> {
        (
            (
                opt(token_word("static")),
                MethodName::parse,
                opt(token("?")),
                opt(GenericsDeclaration::parse),
                delimited(
                    token('('),
                    separated0(MethodArg::parse, token(',')),
                    token(')'),
                ),
            ),
            opt(preceded(token(':'), TsType::parse)),
        )
            .parse_next(input)
            .map(|((is_static, name, optional, generics, args), ret)| Self {
                name,
                generics: generics.unwrap_or_default(),
                args,
                ret,
                optional: optional.is_some(),
                is_static: is_static.is_some(),
            })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MethodArg<'a> {
    pub name: &'a str,
    pub optional: bool,
    pub ty: TsType<'a>,
    pub variadic: bool,
}
impl<'a> Parsable<'a> for MethodArg<'a> {
    fn parse(input: &mut &'a str) -> PResult<Self> {
        separated_pair(
            (opt(token("...")), word1, opt(token('?'))),
            token(':'),
            TsType::parse,
        )
        .map(|((variadic, name, optional), ty)| Self {
            name,
            optional: optional.is_some(),
            ty,
            variadic: variadic.is_some(),
        })
        .parse_next(input)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum MethodName<'a> {
    Nothing,
    Constructor,
    Iterator,
    Name(&'a str),
}
impl<'a> Parsable<'a> for MethodName<'a> {
    fn parse(input: &mut &'a str) -> PResult<Self> {
        alt((
            delimited(token('['), "Symbol.iterator", token(']')).map(|_| Self::Iterator),
            word0.map(|s| match s {
                "" => Self::Nothing,
                "new" | "constructor" => Self::Constructor,
                s => Self::Name(s),
            }),
        ))
        .parse_next(input)
    }
}