//! This module generates AST datatype used by rust-analyzer.
//!
//! Specifically, it generates the `SyntaxKind` enum and a number of newtype
//! wrappers around `SyntaxNode` which implement `syntax::AstNode`.

#![allow(clippy::disallowed_types)]

use std::{
    collections::{BTreeSet, HashSet},
    fmt::Write,
    fs,
};

use either::Either;
use itertools::Itertools;
use proc_macro2::{Punct, Spacing};
use quote::{format_ident, quote};
use stdx::panic_context;
use ungrammar::{Grammar, Rule};

use crate::{
    codegen::{add_preamble, ensure_file_contents, grammar::ast_src::generate_kind_src, reformat},
    project_root,
};

mod ast_src;
use self::ast_src::{AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc};

pub(crate) fn generate(check: bool) {
    let grammar = fs::read_to_string(project_root().join("crates/syntax/rust.ungram"))
        .unwrap()
        .parse()
        .unwrap();
    let ast = lower(&grammar);
    let kinds_src = generate_kind_src(&ast.nodes, &ast.enums, &grammar);

    let syntax_kinds = generate_syntax_kinds(kinds_src);
    let syntax_kinds_file = project_root().join("crates/parser/src/syntax_kind/generated.rs");
    ensure_file_contents(
        crate::flags::CodegenType::Grammar,
        syntax_kinds_file.as_path(),
        &syntax_kinds,
        check,
    );

    let ast_tokens = generate_tokens(&ast);
    let ast_tokens_file = project_root().join("crates/syntax/src/ast/generated/tokens.rs");
    ensure_file_contents(
        crate::flags::CodegenType::Grammar,
        ast_tokens_file.as_path(),
        &ast_tokens,
        check,
    );

    let ast_nodes = generate_nodes(kinds_src, &ast);
    let ast_nodes_file = project_root().join("crates/syntax/src/ast/generated/nodes.rs");
    ensure_file_contents(
        crate::flags::CodegenType::Grammar,
        ast_nodes_file.as_path(),
        &ast_nodes,
        check,
    );
}

fn generate_tokens(grammar: &AstSrc) -> String {
    let tokens = grammar.tokens.iter().map(|token| {
        let name = format_ident!("{}", token);
        let kind = format_ident!("{}", to_upper_snake_case(token));
        quote! {
            pub struct #name {
                pub(crate) syntax: SyntaxToken,
            }
            impl std::fmt::Display for #name {
                fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.syntax, f)
                }
            }
            impl AstToken for #name {
                fn can_cast(kind: SyntaxKind) -> bool { kind == #kind }
                fn cast(syntax: SyntaxToken) -> Option<Self> {
                    if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
                }
                fn syntax(&self) -> &SyntaxToken { &self.syntax }
            }

            impl fmt::Debug for #name {
                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                    f.debug_struct(#token).field("syntax", &self.syntax).finish()
                }
            }
            impl Clone for #name {
                fn clone(&self) -> Self {
                    Self { syntax: self.syntax.clone() }
                }
            }
            impl hash::Hash for #name {
                fn hash<H: hash::Hasher>(&self, state: &mut H) {
                    self.syntax.hash(state);
                }
            }

            impl Eq for #name {}
            impl PartialEq for #name {
                fn eq(&self, other: &Self) -> bool {
                    self.syntax == other.syntax
                }
            }
        }
    });

    add_preamble(
        crate::flags::CodegenType::Grammar,
        reformat(
            quote! {
                use std::{fmt, hash};

                use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken};

                #(#tokens)*
            }
            .to_string(),
        ),
    )
    .replace("#[derive", "\n#[derive")
}

fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
    let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
        .nodes
        .iter()
        .map(|node| {
            let node_str_name = &node.name;
            let name = format_ident!("{}", node.name);
            let kind = format_ident!("{}", to_upper_snake_case(&node.name));
            let traits = node
                .traits
                .iter()
                .filter(|trait_name| {
                    // Loops have two expressions so this might collide, therefore manual impl it
                    node.name != "ForExpr" && node.name != "WhileExpr"
                        || trait_name.as_str() != "HasLoopBody"
                })
                .map(|trait_name| {
                    let trait_name = format_ident!("{}", trait_name);
                    quote!(impl ast::#trait_name for #name {})
                });

            let methods = node.fields.iter().map(|field| {
                let method_name = format_ident!("{}", field.method_name());
                let ty = field.ty();

                if field.is_many() {
                    quote! {
                        #[inline]
                        pub fn #method_name(&self) -> AstChildren<#ty> {
                            support::children(&self.syntax)
                        }
                    }
                } else if let Some(token_kind) = field.token_kind() {
                    quote! {
                        #[inline]
                        pub fn #method_name(&self) -> Option<#ty> {
                            support::token(&self.syntax, #token_kind)
                        }
                    }
                } else {
                    quote! {
                        #[inline]
                        pub fn #method_name(&self) -> Option<#ty> {
                            support::child(&self.syntax)
                        }
                    }
                }
            });
            (
                quote! {
                    #[pretty_doc_comment_placeholder_workaround]
                    pub struct #name {
                        pub(crate) syntax: SyntaxNode,
                    }

                    #(#traits)*

                    impl #name {
                        #(#methods)*
                    }
                },
                quote! {
                    impl AstNode for #name {
                        #[inline]
                        fn kind() -> SyntaxKind
                        where
                            Self: Sized
                        {
                            #kind
                        }
                        #[inline]
                        fn can_cast(kind: SyntaxKind) -> bool {
                            kind == #kind
                        }
                        #[inline]
                        fn cast(syntax: SyntaxNode) -> Option<Self> {
                            if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
                        }
                        #[inline]
                        fn syntax(&self) -> &SyntaxNode { &self.syntax }
                    }

                    impl hash::Hash for #name {
                        fn hash<H: hash::Hasher>(&self, state: &mut H) {
                            self.syntax.hash(state);
                        }
                    }

                    impl Eq for #name {}
                    impl PartialEq for #name {
                        fn eq(&self, other: &Self) -> bool {
                            self.syntax == other.syntax
                        }
                    }

                    impl Clone for #name {
                        fn clone(&self) -> Self {
                            Self { syntax: self.syntax.clone() }
                        }
                    }

                    impl fmt::Debug for #name {
                        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                            f.debug_struct(#node_str_name).field("syntax", &self.syntax).finish()
                        }
                    }
                },
            )
        })
        .unzip();

    let (enum_defs, enum_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
        .enums
        .iter()
        .map(|en| {
            let variants: Vec<_> =
                en.variants.iter().map(|var| format_ident!("{}", var)).sorted().collect();
            let name = format_ident!("{}", en.name);
            let kinds: Vec<_> = variants
                .iter()
                .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string())))
                .collect();
            let traits = en.traits.iter().sorted().map(|trait_name| {
                let trait_name = format_ident!("{}", trait_name);
                quote!(impl ast::#trait_name for #name {})
            });

            let ast_node = if en.name == "Stmt" {
                quote! {}
            } else {
                quote! {
                    impl AstNode for #name {
                        #[inline]
                        fn can_cast(kind: SyntaxKind) -> bool {
                            matches!(kind, #(#kinds)|*)
                        }
                        #[inline]
                        fn cast(syntax: SyntaxNode) -> Option<Self> {
                            let res = match syntax.kind() {
                                #(
                                #kinds => #name::#variants(#variants { syntax }),
                                )*
                                _ => return None,
                            };
                            Some(res)
                        }
                        #[inline]
                        fn syntax(&self) -> &SyntaxNode {
                            match self {
                                #(
                                #name::#variants(it) => &it.syntax,
                                )*
                            }
                        }
                    }
                }
            };

            (
                quote! {
                    #[pretty_doc_comment_placeholder_workaround]
                    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
                    pub enum #name {
                        #(#variants(#variants),)*
                    }

                    #(#traits)*
                },
                quote! {
                    #(
                        impl From<#variants> for #name {
                            #[inline]
                            fn from(node: #variants) -> #name {
                                #name::#variants(node)
                            }
                        }
                    )*
                    #ast_node
                },
            )
        })
        .unzip();
    let (any_node_defs, any_node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
        .nodes
        .iter()
        .flat_map(|node| node.traits.iter().map(move |t| (t, node)))
        .into_group_map()
        .into_iter()
        .sorted_by_key(|(name, _)| *name)
        .map(|(trait_name, nodes)| {
            let name = format_ident!("Any{}", trait_name);
            let node_str_name = name.to_string();
            let trait_name = format_ident!("{}", trait_name);
            let kinds: Vec<_> = nodes
                .iter()
                .map(|name| format_ident!("{}", to_upper_snake_case(&name.name.to_string())))
                .collect();
            let nodes = nodes.iter().map(|node| format_ident!("{}", node.name));
            (
                quote! {
                    #[pretty_doc_comment_placeholder_workaround]
                    pub struct #name {
                        pub(crate) syntax: SyntaxNode,
                    }
                    impl #name {
                        #[inline]
                        pub fn new<T: ast::#trait_name>(node: T) -> #name {
                            #name {
                                syntax: node.syntax().clone()
                            }
                        }
                    }
                },
                quote! {
                    impl ast::#trait_name for #name {}
                    impl AstNode for #name {
                        #[inline]
                        fn can_cast(kind: SyntaxKind) -> bool {
                            matches!(kind, #(#kinds)|*)
                        }
                        #[inline]
                        fn cast(syntax: SyntaxNode) -> Option<Self> {
                            Self::can_cast(syntax.kind()).then_some(#name { syntax })
                        }
                        #[inline]
                        fn syntax(&self) -> &SyntaxNode {
                            &self.syntax
                        }
                    }

                    impl hash::Hash for #name {
                        fn hash<H: hash::Hasher>(&self, state: &mut H) {
                            self.syntax.hash(state);
                        }
                    }

                    impl Eq for #name {}
                    impl PartialEq for #name {
                        fn eq(&self, other: &Self) -> bool {
                            self.syntax == other.syntax
                        }
                    }

                    impl Clone for #name {
                        fn clone(&self) -> Self {
                            Self { syntax: self.syntax.clone() }
                        }
                    }

                    impl fmt::Debug for #name {
                        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                            f.debug_struct(#node_str_name).field("syntax", &self.syntax).finish()
                        }
                    }

                    #(
                        impl From<#nodes> for #name {
                            #[inline]
                            fn from(node: #nodes) -> #name {
                                #name { syntax: node.syntax }
                            }
                        }
                    )*
                },
            )
        })
        .unzip();

    let enum_names = grammar.enums.iter().map(|it| &it.name);
    let node_names = grammar.nodes.iter().map(|it| &it.name);

    let display_impls =
        enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).map(|name| {
            quote! {
                impl std::fmt::Display for #name {
                    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                        std::fmt::Display::fmt(self.syntax(), f)
                    }
                }
            }
        });

    let defined_nodes: HashSet<_> = node_names.collect();

    for node in kinds
        .nodes
        .iter()
        .map(|kind| to_pascal_case(kind))
        .filter(|name| !defined_nodes.iter().any(|&it| it == name))
    {
        eprintln!("Warning: node {node} not defined in AST source");
        drop(node);
    }

    let ast = quote! {
        #![allow(non_snake_case)]
        use std::{fmt, hash};

        use crate::{
            SyntaxNode, SyntaxToken, SyntaxKind::{self, *},
            ast::{self, AstNode, AstChildren, support},
            T,
        };

        #(#node_defs)*
        #(#enum_defs)*
        #(#any_node_defs)*
        #(#node_boilerplate_impls)*
        #(#enum_boilerplate_impls)*
        #(#any_node_boilerplate_impls)*
        #(#display_impls)*
    };

    let ast = ast.to_string().replace("T ! [", "T![");

    let mut res = String::with_capacity(ast.len() * 2);

    let mut docs =
        grammar.nodes.iter().map(|it| &it.doc).chain(grammar.enums.iter().map(|it| &it.doc));

    for chunk in ast.split("# [pretty_doc_comment_placeholder_workaround] ") {
        res.push_str(chunk);
        if let Some(doc) = docs.next() {
            write_doc_comment(doc, &mut res);
        }
    }

    let res = add_preamble(crate::flags::CodegenType::Grammar, reformat(res));
    res.replace("#[derive", "\n#[derive")
}

fn write_doc_comment(contents: &[String], dest: &mut String) {
    for line in contents {
        writeln!(dest, "///{line}").unwrap();
    }
}

fn generate_syntax_kinds(grammar: KindsSrc) -> String {
    let (single_byte_tokens_values, single_byte_tokens): (Vec<_>, Vec<_>) = grammar
        .punct
        .iter()
        .filter(|(token, _name)| token.len() == 1)
        .map(|(token, name)| (token.chars().next().unwrap(), format_ident!("{}", name)))
        .unzip();

    let punctuation_values = grammar.punct.iter().map(|(token, _name)| {
        if "{}[]()".contains(token) {
            let c = token.chars().next().unwrap();
            quote! { #c }
            // underscore is an identifier in the proc-macro api
        } else if *token == "_" {
            quote! { _ }
        } else {
            let cs = token.chars().map(|c| Punct::new(c, Spacing::Joint));
            quote! { #(#cs)* }
        }
    });
    let punctuation =
        grammar.punct.iter().map(|(_token, name)| format_ident!("{}", name)).collect::<Vec<_>>();
    let punctuation_texts = grammar.punct.iter().map(|&(text, _name)| text);

    let fmt_kw_as_variant = |&name| match name {
        "Self" => format_ident!("SELF_TYPE_KW"),
        name => format_ident!("{}_KW", to_upper_snake_case(name)),
    };
    let strict_keywords = grammar.keywords;
    let strict_keywords_variants =
        strict_keywords.iter().map(fmt_kw_as_variant).collect::<Vec<_>>();
    let strict_keywords_tokens = strict_keywords.iter().map(|it| format_ident!("{it}"));

    let edition_dependent_keywords_variants_match_arm = grammar
        .edition_dependent_keywords
        .iter()
        .map(|(kw, ed)| {
            let kw = fmt_kw_as_variant(kw);
            quote! { #kw if #ed <= edition }
        })
        .collect::<Vec<_>>();
    let edition_dependent_keywords_str_match_arm = grammar
        .edition_dependent_keywords
        .iter()
        .map(|(kw, ed)| {
            quote! { #kw if #ed <= edition }
        })
        .collect::<Vec<_>>();
    let edition_dependent_keywords = grammar.edition_dependent_keywords.iter().map(|&(it, _)| it);
    let edition_dependent_keywords_variants = grammar
        .edition_dependent_keywords
        .iter()
        .map(|(kw, _)| fmt_kw_as_variant(kw))
        .collect::<Vec<_>>();
    let edition_dependent_keywords_tokens =
        grammar.edition_dependent_keywords.iter().map(|(it, _)| format_ident!("{it}"));

    let contextual_keywords = grammar.contextual_keywords;
    let contextual_keywords_variants =
        contextual_keywords.iter().map(fmt_kw_as_variant).collect::<Vec<_>>();
    let contextual_keywords_tokens = contextual_keywords.iter().map(|it| format_ident!("{it}"));
    let contextual_keywords_str_match_arm = grammar.contextual_keywords.iter().map(|kw| {
        match grammar.edition_dependent_keywords.iter().find(|(ed_kw, _)| ed_kw == kw) {
            Some((_, ed)) => quote! { #kw if edition < #ed },
            None => quote! { #kw },
        }
    });
    let contextual_keywords_variants_match_arm = grammar
        .contextual_keywords
        .iter()
        .map(|kw_s| {
            let kw = fmt_kw_as_variant(kw_s);
            match grammar.edition_dependent_keywords.iter().find(|(ed_kw, _)| ed_kw == kw_s) {
                Some((_, ed)) => quote! { #kw if edition < #ed },
                None => quote! { #kw },
            }
        })
        .collect::<Vec<_>>();

    let non_strict_keyword_variants = contextual_keywords_variants
        .iter()
        .chain(edition_dependent_keywords_variants.iter())
        .sorted()
        .dedup()
        .collect::<Vec<_>>();

    let literals =
        grammar.literals.iter().map(|name| format_ident!("{}", name)).collect::<Vec<_>>();

    let tokens = grammar.tokens.iter().map(|name| format_ident!("{}", name)).collect::<Vec<_>>();

    let nodes = grammar.nodes.iter().map(|name| format_ident!("{}", name)).collect::<Vec<_>>();

    let ast = quote! {
        #![allow(bad_style, missing_docs, unreachable_pub)]
        use crate::Edition;

        /// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT`.
        #[derive(Debug)]
        #[repr(u16)]
        pub enum SyntaxKind {
            // Technical SyntaxKinds: they appear temporally during parsing,
            // but never end up in the final tree
            #[doc(hidden)]
            TOMBSTONE,
            #[doc(hidden)]
            EOF,
            #(#punctuation,)*
            #(#strict_keywords_variants,)*
            #(#non_strict_keyword_variants,)*
            #(#literals,)*
            #(#tokens,)*
            #(#nodes,)*

            // Technical kind so that we can cast from u16 safely
            #[doc(hidden)]
            __LAST,
        }
        use self::SyntaxKind::*;

        impl SyntaxKind {
            #[allow(unreachable_patterns)]
            pub const fn text(self) -> &'static str {
                match self {
                    TOMBSTONE | EOF | __LAST
                    #( | #literals )*
                    #( | #nodes )*
                    #( | #tokens )* => panic!("no text for these `SyntaxKind`s"),
                    #( #punctuation => #punctuation_texts ,)*
                    #( #strict_keywords_variants => #strict_keywords ,)*
                    #( #contextual_keywords_variants => #contextual_keywords ,)*
                    #( #edition_dependent_keywords_variants => #edition_dependent_keywords ,)*
                }
            }

            /// Checks whether this syntax kind is a strict keyword for the given edition.
            /// Strict keywords are identifiers that are always considered keywords.
            pub fn is_strict_keyword(self, edition: Edition) -> bool {
                matches!(self, #(#strict_keywords_variants)|*)
                || match self {
                    #(#edition_dependent_keywords_variants_match_arm => true,)*
                    _ => false,
                }
            }

            /// Checks whether this syntax kind is a weak keyword for the given edition.
            /// Weak keywords are identifiers that are considered keywords only in certain contexts.
            pub fn is_contextual_keyword(self, edition: Edition) -> bool {
                match self {
                    #(#contextual_keywords_variants_match_arm => true,)*
                    _ => false,
                }
            }

            /// Checks whether this syntax kind is a strict or weak keyword for the given edition.
            pub fn is_keyword(self, edition: Edition) -> bool {
                matches!(self, #(#strict_keywords_variants)|*)
                || match self {
                    #(#edition_dependent_keywords_variants_match_arm => true,)*
                    #(#contextual_keywords_variants_match_arm => true,)*
                    _ => false,
                }
            }

            pub fn is_punct(self) -> bool {
                matches!(self, #(#punctuation)|*)
            }

            pub fn is_literal(self) -> bool {
                matches!(self, #(#literals)|*)
            }

            pub fn from_keyword(ident: &str, edition: Edition) -> Option<SyntaxKind> {
                let kw = match ident {
                    #(#strict_keywords => #strict_keywords_variants,)*
                    #(#edition_dependent_keywords_str_match_arm => #edition_dependent_keywords_variants,)*
                    _ => return None,
                };
                Some(kw)
            }

            pub fn from_contextual_keyword(ident: &str, edition: Edition) -> Option<SyntaxKind> {
                let kw = match ident {
                    #(#contextual_keywords_str_match_arm => #contextual_keywords_variants,)*
                    _ => return None,
                };
                Some(kw)
            }

            pub fn from_char(c: char) -> Option<SyntaxKind> {
                let tok = match c {
                    #(#single_byte_tokens_values => #single_byte_tokens,)*
                    _ => return None,
                };
                Some(tok)
            }
        }

        /// `T![]`
        #[macro_export]
        macro_rules! T_ {
            #([#punctuation_values] => { $crate::SyntaxKind::#punctuation };)*
            #([#strict_keywords_tokens] => { $crate::SyntaxKind::#strict_keywords_variants };)*
            #([#contextual_keywords_tokens] => { $crate::SyntaxKind::#contextual_keywords_variants };)*
            #([#edition_dependent_keywords_tokens] => { $crate::SyntaxKind::#edition_dependent_keywords_variants };)*
            [lifetime_ident] => { $crate::SyntaxKind::LIFETIME_IDENT };
            [int_number] => { $crate::SyntaxKind::INT_NUMBER };
            [ident] => { $crate::SyntaxKind::IDENT };
            [string] => { $crate::SyntaxKind::STRING };
            [shebang] => { $crate::SyntaxKind::SHEBANG };
            [frontmatter] => { $crate::SyntaxKind::FRONTMATTER };
        }

        impl ::core::marker::Copy for SyntaxKind {}
        impl ::core::clone::Clone for SyntaxKind {
            #[inline]
            fn clone(&self) -> Self {
                *self
            }
        }
        impl ::core::cmp::PartialEq for SyntaxKind {
            #[inline]
            fn eq(&self, other: &Self) -> bool {
                (*self as u16) == (*other as u16)
            }
        }
        impl ::core::cmp::Eq for SyntaxKind {}
        impl ::core::cmp::PartialOrd for SyntaxKind {
            #[inline]
            fn partial_cmp(&self, other: &Self) -> core::option::Option<core::cmp::Ordering> {
                Some(self.cmp(other))
            }
        }
        impl ::core::cmp::Ord for SyntaxKind {
            #[inline]
            fn cmp(&self, other: &Self) -> core::cmp::Ordering {
                (*self as u16).cmp(&(*other as u16))
            }
        }
        impl ::core::hash::Hash for SyntaxKind {
            fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
                ::core::mem::discriminant(self).hash(state);
            }
        }
    };

    let result = add_preamble(crate::flags::CodegenType::Grammar, reformat(ast.to_string()));

    if let Some(start) = result.find("macro_rules ! T_")
        && let Some(macro_end) = result[start..].find("\nimpl ::core::marker::Copy")
    {
        let macro_section = &result[start..start + macro_end];
        let formatted_macro = macro_section
            .replace("T_ { [", "T_ {\n    [")
            .replace(" ; [", ";\n    [")
            .replace(" ; }", ";\n}")
            .trim_end()
            .to_owned()
            + "\n";
        return result.replace(macro_section, &formatted_macro);
    }

    result
}

fn to_upper_snake_case(s: &str) -> String {
    let mut buf = String::with_capacity(s.len());
    let mut prev = false;
    for c in s.chars() {
        if c.is_ascii_uppercase() && prev {
            buf.push('_')
        }
        prev = true;

        buf.push(c.to_ascii_uppercase());
    }
    buf
}

fn to_lower_snake_case(s: &str) -> String {
    let mut buf = String::with_capacity(s.len());
    let mut prev = false;
    for c in s.chars() {
        if c.is_ascii_uppercase() && prev {
            buf.push('_')
        }
        prev = true;

        buf.push(c.to_ascii_lowercase());
    }
    buf
}

fn to_pascal_case(s: &str) -> String {
    let mut buf = String::with_capacity(s.len());
    let mut prev_is_underscore = true;
    for c in s.chars() {
        if c == '_' {
            prev_is_underscore = true;
        } else if prev_is_underscore {
            buf.push(c.to_ascii_uppercase());
            prev_is_underscore = false;
        } else {
            buf.push(c.to_ascii_lowercase());
        }
    }
    buf
}

fn pluralize(s: &str) -> String {
    format!("{s}s")
}

impl Field {
    fn is_many(&self) -> bool {
        matches!(self, Field::Node { cardinality: Cardinality::Many, .. })
    }
    fn token_kind(&self) -> Option<proc_macro2::TokenStream> {
        match self {
            Field::Token { token, .. } => {
                let token: proc_macro2::TokenStream = token.parse().unwrap();
                Some(quote! { T![#token] })
            }
            _ => None,
        }
    }
    fn method_name(&self) -> String {
        match self {
            Field::Token { name, token, .. } => {
                if let Some(name) = name {
                    return name.clone();
                }
                let name = match token.as_str() {
                    ";" => "semicolon",
                    "->" => "thin_arrow",
                    "'{'" => "l_curly",
                    "'}'" => "r_curly",
                    "'('" => "l_paren",
                    "')'" => "r_paren",
                    "'['" => "l_brack",
                    "']'" => "r_brack",
                    "<" => "l_angle",
                    ">" => "r_angle",
                    "=" => "eq",
                    "!" => "excl",
                    "*" => "star",
                    "&" => "amp",
                    "-" => "minus",
                    "_" => "underscore",
                    "." => "dot",
                    ".." => "dotdot",
                    "..." => "dotdotdot",
                    "..=" => "dotdoteq",
                    "=>" => "fat_arrow",
                    "@" => "at",
                    ":" => "colon",
                    "::" => "coloncolon",
                    "#" => "pound",
                    "?" => "question_mark",
                    "," => "comma",
                    "|" => "pipe",
                    "~" => "tilde",
                    _ => token,
                };
                format!("{name}_token",)
            }
            Field::Node { name, .. } => {
                if name == "type" {
                    String::from("ty")
                } else {
                    name.to_owned()
                }
            }
        }
    }
    fn ty(&self) -> proc_macro2::Ident {
        match self {
            Field::Token { .. } => format_ident!("SyntaxToken"),
            Field::Node { ty, .. } => format_ident!("{}", ty),
        }
    }
}

fn clean_token_name(name: &str) -> String {
    let cleaned = name.trim_start_matches(['@', '#', '?']);
    if cleaned.is_empty() { name.to_owned() } else { cleaned.to_owned() }
}

fn lower(grammar: &Grammar) -> AstSrc {
    let mut res = AstSrc {
        tokens:
            "Whitespace Comment String ByteString CString IntNumber FloatNumber Char Byte Ident"
                .split_ascii_whitespace()
                .map(|it| it.to_owned())
                .collect::<Vec<_>>(),
        ..Default::default()
    };

    let nodes = grammar.iter().collect::<Vec<_>>();

    for &node in &nodes {
        let name = grammar[node].name.clone();
        let rule = &grammar[node].rule;
        let _g = panic_context::enter(name.clone());
        match lower_enum(grammar, rule) {
            Some(variants) => {
                let enum_src = AstEnumSrc { doc: Vec::new(), name, traits: Vec::new(), variants };
                res.enums.push(enum_src);
            }
            None => {
                let mut fields = Vec::new();
                lower_rule(&mut fields, grammar, None, rule);
                res.nodes.push(AstNodeSrc { doc: Vec::new(), name, traits: Vec::new(), fields });
            }
        }
    }

    deduplicate_fields(&mut res);
    extract_enums(&mut res);
    extract_struct_traits(&mut res);
    extract_enum_traits(&mut res);
    res.nodes.sort_by_key(|it| it.name.clone());
    res.enums.sort_by_key(|it| it.name.clone());
    res.tokens.sort();
    res.nodes.iter_mut().for_each(|it| {
        it.traits.sort();
        it.fields.sort_by_key(|it| match it {
            Field::Token { token, .. } => (true, token.clone()),
            Field::Node { name, .. } => (false, name.clone()),
        });
    });
    res.enums.iter_mut().for_each(|it| {
        it.traits.sort();
        it.variants.sort();
    });
    res
}

fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option<Vec<String>> {
    let alternatives = match rule {
        Rule::Alt(it) => it,
        _ => return None,
    };
    let mut variants = Vec::new();
    for alternative in alternatives {
        match alternative {
            Rule::Node(it) => variants.push(grammar[*it].name.clone()),
            Rule::Token(it) if grammar[*it].name == ";" => (),
            _ => return None,
        }
    }
    Some(variants)
}

fn lower_rule(acc: &mut Vec<Field>, grammar: &Grammar, label: Option<&String>, rule: &Rule) {
    if lower_separated_list(acc, grammar, label, rule) {
        return;
    }

    match rule {
        Rule::Node(node) => {
            let ty = grammar[*node].name.clone();
            let name = label.cloned().unwrap_or_else(|| to_lower_snake_case(&ty));
            let field = Field::Node { name, ty, cardinality: Cardinality::Optional };
            acc.push(field);
        }
        Rule::Token(token) => {
            let mut token = clean_token_name(&grammar[*token].name);
            if "[]{}()".contains(&token) {
                token = format!("'{token}'");
            }
            let field = Field::Token { name: label.cloned(), token };
            acc.push(field);
        }
        Rule::Rep(inner) => {
            if let Rule::Node(node) = &**inner {
                let ty = grammar[*node].name.clone();
                let name = label.cloned().unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty)));
                let field = Field::Node { name, ty, cardinality: Cardinality::Many };
                acc.push(field);
                return;
            }
            panic!("unhandled rule: {rule:?}")
        }
        Rule::Labeled { label: l, rule } => {
            assert!(label.is_none());
            let manually_implemented = matches!(
                l.as_str(),
                "lhs"
                    | "rhs"
                    | "then_branch"
                    | "else_branch"
                    | "start"
                    | "end"
                    | "op"
                    | "index"
                    | "base"
                    | "value"
                    | "trait"
                    | "self_ty"
                    | "iterable"
                    | "condition"
                    | "args"
                    | "body"
            );
            if manually_implemented {
                return;
            }
            lower_rule(acc, grammar, Some(l), rule);
        }
        Rule::Seq(rules) | Rule::Alt(rules) => {
            for rule in rules {
                lower_rule(acc, grammar, label, rule)
            }
        }
        Rule::Opt(rule) => lower_rule(acc, grammar, label, rule),
    }
}

// (T (',' T)* ','?)
fn lower_separated_list(
    acc: &mut Vec<Field>,
    grammar: &Grammar,
    label: Option<&String>,
    rule: &Rule,
) -> bool {
    let rule = match rule {
        Rule::Seq(it) => it,
        _ => return false,
    };

    let (nt, repeat, trailing_sep) = match rule.as_slice() {
        [Rule::Node(node), Rule::Rep(repeat), Rule::Opt(trailing_sep)] => {
            (Either::Left(node), repeat, Some(trailing_sep))
        }
        [Rule::Node(node), Rule::Rep(repeat)] => (Either::Left(node), repeat, None),
        [Rule::Token(token), Rule::Rep(repeat), Rule::Opt(trailing_sep)] => {
            (Either::Right(token), repeat, Some(trailing_sep))
        }
        [Rule::Token(token), Rule::Rep(repeat)] => (Either::Right(token), repeat, None),
        _ => return false,
    };
    let repeat = match &**repeat {
        Rule::Seq(it) => it,
        _ => return false,
    };
    if !matches!(
        repeat.as_slice(),
        [comma, nt_]
            if trailing_sep.is_none_or(|it| comma == &**it) && match (nt, nt_) {
                (Either::Left(node), Rule::Node(nt_)) => node == nt_,
                (Either::Right(token), Rule::Token(nt_)) => token == nt_,
                _ => false,
            }
    ) {
        return false;
    }
    match nt {
        Either::Right(token) => {
            let token = clean_token_name(&grammar[*token].name);
            let field = Field::Token { token, name: None };
            acc.push(field);
        }
        Either::Left(node) => {
            let ty = grammar[*node].name.clone();
            let name = label.cloned().unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty)));
            let field = Field::Node { name, ty, cardinality: Cardinality::Many };
            acc.push(field);
        }
    }
    true
}

fn deduplicate_fields(ast: &mut AstSrc) {
    for node in &mut ast.nodes {
        let mut i = 0;
        'outer: while i < node.fields.len() {
            for j in 0..i {
                let f1 = &node.fields[i];
                let f2 = &node.fields[j];
                if f1 == f2 {
                    node.fields.remove(i);
                    continue 'outer;
                }
            }
            i += 1;
        }
    }
}

fn extract_enums(ast: &mut AstSrc) {
    for node in &mut ast.nodes {
        for enm in &ast.enums {
            let mut to_remove = Vec::new();
            for (i, field) in node.fields.iter().enumerate() {
                let ty = field.ty().to_string();
                if enm.variants.iter().any(|it| it == &ty) {
                    to_remove.push(i);
                }
            }
            if to_remove.len() == enm.variants.len() {
                node.remove_field(to_remove);
                let ty = enm.name.clone();
                let name = to_lower_snake_case(&ty);
                node.fields.push(Field::Node { name, ty, cardinality: Cardinality::Optional });
            }
        }
    }
}

const TRAITS: &[(&str, &[&str])] = &[
    ("HasAttrs", &["attrs"]),
    ("HasName", &["name"]),
    ("HasVisibility", &["visibility"]),
    ("HasGenericParams", &["generic_param_list", "where_clause"]),
    ("HasGenericArgs", &["generic_arg_list"]),
    ("HasTypeBounds", &["type_bound_list", "colon_token"]),
    ("HasModuleItem", &["items"]),
    ("HasLoopBody", &["label", "loop_body"]),
    ("HasArgList", &["arg_list"]),
];

fn extract_struct_traits(ast: &mut AstSrc) {
    for node in &mut ast.nodes {
        for (name, methods) in TRAITS {
            extract_struct_trait(node, name, methods);
        }
    }

    let nodes_with_doc_comments = [
        "SourceFile",
        "Fn",
        "Struct",
        "Union",
        "RecordField",
        "TupleField",
        "Enum",
        "Variant",
        "Trait",
        "Module",
        "Static",
        "Const",
        "TypeAlias",
        "Impl",
        "ExternBlock",
        "ExternCrate",
        "MacroCall",
        "MacroRules",
        "MacroDef",
        "Use",
    ];

    for node in &mut ast.nodes {
        if nodes_with_doc_comments.contains(&&*node.name) {
            node.traits.push("HasDocComments".into());
        }
    }
}

fn extract_struct_trait(node: &mut AstNodeSrc, trait_name: &str, methods: &[&str]) {
    let mut to_remove = Vec::new();
    for (i, field) in node.fields.iter().enumerate() {
        let method_name = field.method_name();
        if methods.iter().any(|&it| it == method_name) {
            to_remove.push(i);
        }
    }
    if to_remove.len() == methods.len() {
        node.traits.push(trait_name.to_owned());
        node.remove_field(to_remove);
    }
}

fn extract_enum_traits(ast: &mut AstSrc) {
    for enm in &mut ast.enums {
        if enm.name == "Stmt" {
            continue;
        }
        let nodes = &ast.nodes;
        let mut variant_traits = enm
            .variants
            .iter()
            .map(|var| nodes.iter().find(|it| &it.name == var).unwrap())
            .map(|node| node.traits.iter().cloned().collect::<BTreeSet<_>>());

        let mut enum_traits = match variant_traits.next() {
            Some(it) => it,
            None => continue,
        };
        for traits in variant_traits {
            enum_traits = enum_traits.intersection(&traits).cloned().collect();
        }
        enm.traits = enum_traits.into_iter().collect();
    }
}

impl AstNodeSrc {
    fn remove_field(&mut self, to_remove: Vec<usize>) {
        to_remove.into_iter().rev().for_each(|idx| {
            self.fields.remove(idx);
        });
    }
}

#[test]
fn test() {
    generate(true);
}
