<commit_before>//! Various extension methods to ast Nodes, which are hard to code-generate.
//! Extensions for various expressions live in a sibling `expr_extensions` module.

use std::{borrow::Cow, fmt, iter::successors};

use itertools::Itertools;
use parser::SyntaxKind;
use rowan::{GreenNodeData, GreenTokenData, NodeOrToken};

use crate::{
    ast::{self, support, AstNode, AstToken, AttrsOwner, NameOwner, SyntaxNode},
    SmolStr, SyntaxElement, SyntaxToken, TokenText, T,
};

impl ast::Lifetime {
    pub fn text(&self) -> TokenText<'_> {
        text_of_first_token(self.syntax())
    }
}

impl ast::Name {
    pub fn text(&self) -> TokenText<'_> {
        text_of_first_token(self.syntax())
    }
}

impl ast::NameRef {
    pub fn text(&self) -> TokenText<'_> {
        text_of_first_token(self.syntax())
    }

    pub fn as_tuple_field(&self) -> Option<usize> {
        self.text().parse().ok()
    }
}

fn _text_of_first_token(node: &SyntaxNode) -> Cow<'_, str> {
    fn cow_map<F: FnOnce(&GreenNodeData) -> &str>(green: Cow<GreenNodeData>, f: F) -> Cow<str> {
        match green {
            Cow::Borrowed(green_ref) => Cow::Borrowed(f(green_ref)),
            Cow::Owned(green) => Cow::Owned(f(&green).to_owned()),
        }
    }

    cow_map(node.green(), |green_ref| {
        green_ref.children().next().and_then(NodeOrToken::into_token).unwrap().text()
    })
}

fn text_of_first_token(node: &SyntaxNode) -> TokenText<'_> {
    fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData {
        green_ref.children().next().and_then(NodeOrToken::into_token).unwrap()
    }

    match node.green() {
        Cow::Borrowed(green_ref) => TokenText::Borrowed(first_token(green_ref).text()),
        Cow::Owned(green) => TokenText::Owned(first_token(&green).to_owned()),
    }
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Macro {
    MacroRules(ast::MacroRules),
    MacroDef(ast::MacroDef),<commit_msg>Clean up<commit_after>//! Various extension methods to ast Nodes, which are hard to code-generate.
//! Extensions for various expressions live in a sibling `expr_extensions` module.

use std::{borrow::Cow, fmt, iter::successors};

use itertools::Itertools;
use parser::SyntaxKind;
use rowan::{GreenNodeData, GreenTokenData};

use crate::{
    ast::{self, support, AstNode, AstToken, AttrsOwner, NameOwner, SyntaxNode},
    NodeOrToken, SmolStr, SyntaxElement, SyntaxToken, TokenText, T,
};

impl ast::Lifetime {
    pub fn text(&self) -> TokenText<'_> {
        text_of_first_token(self.syntax())
    }
}

impl ast::Name {
    pub fn text(&self) -> TokenText<'_> {
        text_of_first_token(self.syntax())
    }
}

impl ast::NameRef {
    pub fn text(&self) -> TokenText<'_> {
        text_of_first_token(self.syntax())
    }

    pub fn as_tuple_field(&self) -> Option<usize> {
        self.text().parse().ok()
    }
}

fn text_of_first_token(node: &SyntaxNode) -> TokenText<'_> {
    fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData {
        green_ref.children().next().and_then(NodeOrToken::into_token).unwrap()
    }

    match node.green() {
        Cow::Borrowed(green_ref) => TokenText::Borrowed(first_token(green_ref).text()),
        Cow::Owned(green) => TokenText::Owned(first_token(&green).to_owned()),
    }
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Macro {
    MacroRules(ast::MacroRules),
    MacroDef(ast::MacroDef),
{'fraction_non_alphanumeric': 0.16105200945626477, 'fraction_numerical': 0.0, 'mean_word_length': 3.970631424375918, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2742600', 'n_tokens_mistral': 1171, 'n_tokens_neox': 1176, 'n_words': 218}