<commit_before>use std::iter::IntoIterator;

use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span, Spanned, respan};
use syntax::ptr::P;

use invoke::{Invoke, Identity};

use expr::ExprBuilder;
use ident::ToIdent;
use path::PathBuilder;

//////////////////////////////////////////////////////////////////////////////

pub struct PatBuilder<F=Identity> {
    callback: F,
    span: Span,
}

impl PatBuilder {
    pub fn new() -> Self {
        PatBuilder::new_with_callback(Identity)
    }
}


impl<F> PatBuilder<F>
    where F: Invoke<P<ast::Pat>>,
{
    pub fn new_with_callback(callback: F) -> Self {
        PatBuilder {
            callback: callback,
            span: DUMMY_SP,
        }
    }

    pub fn span(mut self, span: Span) -> Self {
        self.span = span;
        self
    }

    pub fn build(self, pat: P<ast::Pat>) -> F::Result {
        self.callback.invoke(pat)
    }

    pub fn build_pat_(self, pat_: ast::Pat_) -> F::Result {
        let span = self.span;
        self.build(P(ast::Pat {
            id: ast::DUMMY_NODE_ID,
            node: pat_,
            span: span,
        }))
    }

    pub fn wild(self) -> F::Result {
        self.build_pat_(ast::Pat_::PatWild(ast::PatWildKind::PatWildSingle))
    }

    pub fn wild_multi(self) -> F::Result {
        self.build_pat_(ast::Pat_::PatWild(ast::PatWildKind::PatWildMulti))
    }

    pub fn build_id<I>(self, mode: ast::BindingMode, id: I, sub: Option<P<ast::Pat>>) -> F::Result
        where I: ToIdent,
    {
        let id = respan(self.span, id.to_ident());

        self.build_pat_(ast::Pat_::PatIdent(mode, id, sub))
    }

    pub fn id<I>(self, id: I) -> F::Result
        where I: ToIdent
    {
        let mode = ast::BindingMode::BindByValue(ast::Mutability::MutImmutable);
        self.build_id(mode, id, None)
    }

    pub fn mut_id<I>(self, id: I) -> F::Result
        where I: ToIdent
    {
        let mode = ast::BindingMode::BindByValue(ast::Mutability::MutMutable);
        self.build_id(mode, id, None)
    }

    pub fn ref_id<I>(self, id: I) -> F::Result
        where I: ToIdent
    {
        let mode = ast::BindingMode::BindByRef(ast::Mutability::MutImmutable);
        self.build_id(mode, id, None)
    }

    pub fn ref_mut_id<I>(self, id: I) -> F::Result
        where I: ToIdent
    {
        let mode = ast::BindingMode::BindByRef(ast::Mutability::MutMutable);
        self.build_id(mode, id, None)
    }

    pub fn enum_(self) -> PathBuilder<PatEnumBuilder<F>> {
        PathBuilder::new_with_callback(PatEnumBuilder(self))
    }

    pub fn struct_(self) -> PathBuilder<PatStructBuilder<F>> {
        PathBuilder::new_with_callback(PatStructBuilder(self))
    }

    pub fn expr(self) -> ExprBuilder<PatExprBuilder<F>> {
        ExprBuilder::new_with_callback(PatExprBuilder(self))
    }

    pub fn tuple(self) -> PatTupleBuilder<F> {
        PatTupleBuilder {
            builder: self,
            pats: Vec::new(),
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct PatEnumBuilder<F>(PatBuilder<F>);

impl<F> Invoke<ast::Path> for PatEnumBuilder<F> {
    type Result = PatEnumPathBuilder<F>;

    fn invoke(self, path: ast::Path) -> PatEnumPathBuilder<F> {
        PatEnumPathBuilder {
            builder: self.0,
            path: path,
            pats: Vec::new(),
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct PatEnumPathBuilder<F> {
    builder: PatBuilder<F>,
    path: ast::Path,
    pats: Vec<P<ast::Pat>>,
}

impl<F> PatEnumPathBuilder<F>
    where F: Invoke<P<ast::Pat>>,
{
    pub fn with_pats<I>(mut self, iter: I) -> Self
        where I: IntoIterator<Item=P<ast::Pat>>,
    {
        self.pats.extend(iter);
        self
    }

    pub fn pat(self) -> PatBuilder<Self> {
        PatBuilder::new_with_callback(self)
    }

    pub fn with_ids<I, T>(mut self, iter: I) -> Self
        where I: IntoIterator<Item=T>,
              T: ToIdent,
    {
        for id in iter {
            self = self.id(id);
        }
        self
    }

    pub fn id<I>(self, id: I) -> Self
        where I: ToIdent
    {
        self.pat().id(id)
    }

    pub fn build(self) -> F::Result {
        let pats = if self.pats.is_empty() { None } else { Some(self.pats) };

        self.builder.build_pat_(ast::Pat_::PatEnum(self.path, pats))
    }
}

impl<F> Invoke<P<ast::Pat>> for PatEnumPathBuilder<F><commit_msg>Don't treat empty enum patterns as `pat(..)`<commit_after>use std::iter::IntoIterator;

use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span, Spanned, respan};
use syntax::ptr::P;

use invoke::{Invoke, Identity};

use expr::ExprBuilder;
use ident::ToIdent;
use path::PathBuilder;

//////////////////////////////////////////////////////////////////////////////

pub struct PatBuilder<F=Identity> {
    callback: F,
    span: Span,
}

impl PatBuilder {
    pub fn new() -> Self {
        PatBuilder::new_with_callback(Identity)
    }
}


impl<F> PatBuilder<F>
    where F: Invoke<P<ast::Pat>>,
{
    pub fn new_with_callback(callback: F) -> Self {
        PatBuilder {
            callback: callback,
            span: DUMMY_SP,
        }
    }

    pub fn span(mut self, span: Span) -> Self {
        self.span = span;
        self
    }

    pub fn build(self, pat: P<ast::Pat>) -> F::Result {
        self.callback.invoke(pat)
    }

    pub fn build_pat_(self, pat_: ast::Pat_) -> F::Result {
        let span = self.span;
        self.build(P(ast::Pat {
            id: ast::DUMMY_NODE_ID,
            node: pat_,
            span: span,
        }))
    }

    pub fn wild(self) -> F::Result {
        self.build_pat_(ast::Pat_::PatWild(ast::PatWildKind::PatWildSingle))
    }

    pub fn wild_multi(self) -> F::Result {
        self.build_pat_(ast::Pat_::PatWild(ast::PatWildKind::PatWildMulti))
    }

    pub fn build_id<I>(self, mode: ast::BindingMode, id: I, sub: Option<P<ast::Pat>>) -> F::Result
        where I: ToIdent,
    {
        let id = respan(self.span, id.to_ident());

        self.build_pat_(ast::Pat_::PatIdent(mode, id, sub))
    }

    pub fn id<I>(self, id: I) -> F::Result
        where I: ToIdent
    {
        let mode = ast::BindingMode::BindByValue(ast::Mutability::MutImmutable);
        self.build_id(mode, id, None)
    }

    pub fn mut_id<I>(self, id: I) -> F::Result
        where I: ToIdent
    {
        let mode = ast::BindingMode::BindByValue(ast::Mutability::MutMutable);
        self.build_id(mode, id, None)
    }

    pub fn ref_id<I>(self, id: I) -> F::Result
        where I: ToIdent
    {
        let mode = ast::BindingMode::BindByRef(ast::Mutability::MutImmutable);
        self.build_id(mode, id, None)
    }

    pub fn ref_mut_id<I>(self, id: I) -> F::Result
        where I: ToIdent
    {
        let mode = ast::BindingMode::BindByRef(ast::Mutability::MutMutable);
        self.build_id(mode, id, None)
    }

    pub fn enum_(self) -> PathBuilder<PatEnumBuilder<F>> {
        PathBuilder::new_with_callback(PatEnumBuilder(self))
    }

    pub fn struct_(self) -> PathBuilder<PatStructBuilder<F>> {
        PathBuilder::new_with_callback(PatStructBuilder(self))
    }

    pub fn expr(self) -> ExprBuilder<PatExprBuilder<F>> {
        ExprBuilder::new_with_callback(PatExprBuilder(self))
    }

    pub fn tuple(self) -> PatTupleBuilder<F> {
        PatTupleBuilder {
            builder: self,
            pats: Vec::new(),
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct PatEnumBuilder<F>(PatBuilder<F>);

impl<F> Invoke<ast::Path> for PatEnumBuilder<F> {
    type Result = PatEnumPathBuilder<F>;

    fn invoke(self, path: ast::Path) -> PatEnumPathBuilder<F> {
        PatEnumPathBuilder {
            builder: self.0,
            path: path,
            pats: Vec::new(),
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct PatEnumPathBuilder<F> {
    builder: PatBuilder<F>,
    path: ast::Path,
    pats: Vec<P<ast::Pat>>,
}

impl<F> PatEnumPathBuilder<F>
    where F: Invoke<P<ast::Pat>>,
{
    pub fn with_pats<I>(mut self, iter: I) -> Self
        where I: IntoIterator<Item=P<ast::Pat>>,
    {
        self.pats.extend(iter);
        self
    }

    pub fn pat(self) -> PatBuilder<Self> {
        PatBuilder::new_with_callback(self)
    }

    pub fn with_ids<I, T>(mut self, iter: I) -> Self
        where I: IntoIterator<Item=T>,
              T: ToIdent,
    {
        for id in iter {
            self = self.id(id);
        }
        self
    }

    pub fn id<I>(self, id: I) -> Self
        where I: ToIdent
    {
        self.pat().id(id)
    }

    pub fn build(self) -> F::Result {
        self.builder.build_pat_(ast::Pat_::PatEnum(self.path, Some(self.pats)))
    }
}

impl<F> Invoke<P<ast::Pat>> for PatEnumPathBuilder<F>
{'fraction_non_alphanumeric': 0.19319589951560212, 'fraction_numerical': 0.00022530134054297624, 'mean_word_length': 2.046671242278655, 'pattern_counts': {'":': 0, '<': 95, '<?xml version=': 0, '>': 139, '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': '4837006', 'n_tokens_mistral': 2965, 'n_tokens_neox': 2908, 'n_words': 590}