diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 6c1dcf336ac5..74d596f32296 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -1974,6 +1974,17 @@ pub enum Adt { Struct(Struct), Union(Union), } +impl Adt { + pub fn into_enum(self) -> Option { + if let Self::Enum(variant) = self { Some(variant) } else { None } + } + pub fn into_struct(self) -> Option { + if let Self::Struct(variant) = self { Some(variant) } else { None } + } + pub fn into_union(self) -> Option { + if let Self::Union(variant) = self { Some(variant) } else { None } + } +} impl ast::HasAttrs for Adt {} impl ast::HasDocComments for Adt {} impl ast::HasGenericParams for Adt {} @@ -1987,6 +1998,20 @@ pub enum AsmOperand { AsmRegOperand(AsmRegOperand), AsmSym(AsmSym), } +impl AsmOperand { + pub fn into_asm_const(self) -> Option { + if let Self::AsmConst(variant) = self { Some(variant) } else { None } + } + pub fn into_asm_label(self) -> Option { + if let Self::AsmLabel(variant) = self { Some(variant) } else { None } + } + pub fn into_asm_reg_operand(self) -> Option { + if let Self::AsmRegOperand(variant) = self { Some(variant) } else { None } + } + pub fn into_asm_sym(self) -> Option { + if let Self::AsmSym(variant) = self { Some(variant) } else { None } + } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum AsmPiece { @@ -1994,6 +2019,17 @@ pub enum AsmPiece { AsmOperandNamed(AsmOperandNamed), AsmOptions(AsmOptions), } +impl AsmPiece { + pub fn into_asm_clobber_abi(self) -> Option { + if let Self::AsmClobberAbi(variant) = self { Some(variant) } else { None } + } + pub fn into_asm_operand_named(self) -> Option { + if let Self::AsmOperandNamed(variant) = self { Some(variant) } else { None } + } + pub fn into_asm_options(self) -> Option { + if let Self::AsmOptions(variant) = self { Some(variant) } else { None } + } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum AssocItem { @@ -2002,6 +2038,20 @@ pub enum AssocItem { MacroCall(MacroCall), TypeAlias(TypeAlias), } +impl AssocItem { + pub fn into_const(self) -> Option { + if let Self::Const(variant) = self { Some(variant) } else { None } + } + pub fn into_fn(self) -> Option { + if let Self::Fn(variant) = self { Some(variant) } else { None } + } + pub fn into_macro_call(self) -> Option { + if let Self::MacroCall(variant) = self { Some(variant) } else { None } + } + pub fn into_type_alias(self) -> Option { + if let Self::TypeAlias(variant) = self { Some(variant) } else { None } + } +} impl ast::HasAttrs for AssocItem {} impl ast::HasDocComments for AssocItem {} @@ -2044,6 +2094,116 @@ pub enum Expr { YeetExpr(YeetExpr), YieldExpr(YieldExpr), } +impl Expr { + pub fn into_array_expr(self) -> Option { + if let Self::ArrayExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_asm_expr(self) -> Option { + if let Self::AsmExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_await_expr(self) -> Option { + if let Self::AwaitExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_become_expr(self) -> Option { + if let Self::BecomeExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_bin_expr(self) -> Option { + if let Self::BinExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_block_expr(self) -> Option { + if let Self::BlockExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_break_expr(self) -> Option { + if let Self::BreakExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_call_expr(self) -> Option { + if let Self::CallExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_cast_expr(self) -> Option { + if let Self::CastExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_closure_expr(self) -> Option { + if let Self::ClosureExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_continue_expr(self) -> Option { + if let Self::ContinueExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_field_expr(self) -> Option { + if let Self::FieldExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_for_expr(self) -> Option { + if let Self::ForExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_format_args_expr(self) -> Option { + if let Self::FormatArgsExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_if_expr(self) -> Option { + if let Self::IfExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_index_expr(self) -> Option { + if let Self::IndexExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_let_expr(self) -> Option { + if let Self::LetExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_literal(self) -> Option { + if let Self::Literal(variant) = self { Some(variant) } else { None } + } + pub fn into_loop_expr(self) -> Option { + if let Self::LoopExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_macro_expr(self) -> Option { + if let Self::MacroExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_match_expr(self) -> Option { + if let Self::MatchExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_method_call_expr(self) -> Option { + if let Self::MethodCallExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_offset_of_expr(self) -> Option { + if let Self::OffsetOfExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_paren_expr(self) -> Option { + if let Self::ParenExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_path_expr(self) -> Option { + if let Self::PathExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_prefix_expr(self) -> Option { + if let Self::PrefixExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_range_expr(self) -> Option { + if let Self::RangeExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_record_expr(self) -> Option { + if let Self::RecordExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_ref_expr(self) -> Option { + if let Self::RefExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_return_expr(self) -> Option { + if let Self::ReturnExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_try_expr(self) -> Option { + if let Self::TryExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_tuple_expr(self) -> Option { + if let Self::TupleExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_underscore_expr(self) -> Option { + if let Self::UnderscoreExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_while_expr(self) -> Option { + if let Self::WhileExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_yeet_expr(self) -> Option { + if let Self::YeetExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_yield_expr(self) -> Option { + if let Self::YieldExpr(variant) = self { Some(variant) } else { None } + } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ExternItem { @@ -2052,6 +2212,20 @@ pub enum ExternItem { Static(Static), TypeAlias(TypeAlias), } +impl ExternItem { + pub fn into_fn(self) -> Option { + if let Self::Fn(variant) = self { Some(variant) } else { None } + } + pub fn into_macro_call(self) -> Option { + if let Self::MacroCall(variant) = self { Some(variant) } else { None } + } + pub fn into_static(self) -> Option { + if let Self::Static(variant) = self { Some(variant) } else { None } + } + pub fn into_type_alias(self) -> Option { + if let Self::TypeAlias(variant) = self { Some(variant) } else { None } + } +} impl ast::HasAttrs for ExternItem {} impl ast::HasDocComments for ExternItem {} @@ -2060,6 +2234,14 @@ pub enum FieldList { RecordFieldList(RecordFieldList), TupleFieldList(TupleFieldList), } +impl FieldList { + pub fn into_record_field_list(self) -> Option { + if let Self::RecordFieldList(variant) = self { Some(variant) } else { None } + } + pub fn into_tuple_field_list(self) -> Option { + if let Self::TupleFieldList(variant) = self { Some(variant) } else { None } + } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum GenericArg { @@ -2068,6 +2250,20 @@ pub enum GenericArg { LifetimeArg(LifetimeArg), TypeArg(TypeArg), } +impl GenericArg { + pub fn into_assoc_type_arg(self) -> Option { + if let Self::AssocTypeArg(variant) = self { Some(variant) } else { None } + } + pub fn into_const_arg(self) -> Option { + if let Self::ConstArg(variant) = self { Some(variant) } else { None } + } + pub fn into_lifetime_arg(self) -> Option { + if let Self::LifetimeArg(variant) = self { Some(variant) } else { None } + } + pub fn into_type_arg(self) -> Option { + if let Self::TypeArg(variant) = self { Some(variant) } else { None } + } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum GenericParam { @@ -2075,6 +2271,17 @@ pub enum GenericParam { LifetimeParam(LifetimeParam), TypeParam(TypeParam), } +impl GenericParam { + pub fn into_const_param(self) -> Option { + if let Self::ConstParam(variant) = self { Some(variant) } else { None } + } + pub fn into_lifetime_param(self) -> Option { + if let Self::LifetimeParam(variant) = self { Some(variant) } else { None } + } + pub fn into_type_param(self) -> Option { + if let Self::TypeParam(variant) = self { Some(variant) } else { None } + } +} impl ast::HasAttrs for GenericParam {} #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -2097,6 +2304,59 @@ pub enum Item { Union(Union), Use(Use), } +impl Item { + pub fn into_asm_expr(self) -> Option { + if let Self::AsmExpr(variant) = self { Some(variant) } else { None } + } + pub fn into_const(self) -> Option { + if let Self::Const(variant) = self { Some(variant) } else { None } + } + pub fn into_enum(self) -> Option { + if let Self::Enum(variant) = self { Some(variant) } else { None } + } + pub fn into_extern_block(self) -> Option { + if let Self::ExternBlock(variant) = self { Some(variant) } else { None } + } + pub fn into_extern_crate(self) -> Option { + if let Self::ExternCrate(variant) = self { Some(variant) } else { None } + } + pub fn into_fn(self) -> Option { + if let Self::Fn(variant) = self { Some(variant) } else { None } + } + pub fn into_impl(self) -> Option { + if let Self::Impl(variant) = self { Some(variant) } else { None } + } + pub fn into_macro_call(self) -> Option { + if let Self::MacroCall(variant) = self { Some(variant) } else { None } + } + pub fn into_macro_def(self) -> Option { + if let Self::MacroDef(variant) = self { Some(variant) } else { None } + } + pub fn into_macro_rules(self) -> Option { + if let Self::MacroRules(variant) = self { Some(variant) } else { None } + } + pub fn into_module(self) -> Option { + if let Self::Module(variant) = self { Some(variant) } else { None } + } + pub fn into_static(self) -> Option { + if let Self::Static(variant) = self { Some(variant) } else { None } + } + pub fn into_struct(self) -> Option { + if let Self::Struct(variant) = self { Some(variant) } else { None } + } + pub fn into_trait(self) -> Option { + if let Self::Trait(variant) = self { Some(variant) } else { None } + } + pub fn into_type_alias(self) -> Option { + if let Self::TypeAlias(variant) = self { Some(variant) } else { None } + } + pub fn into_union(self) -> Option { + if let Self::Union(variant) = self { Some(variant) } else { None } + } + pub fn into_use(self) -> Option { + if let Self::Use(variant) = self { Some(variant) } else { None } + } +} impl ast::HasAttrs for Item {} #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -2118,6 +2378,56 @@ pub enum Pat { TupleStructPat(TupleStructPat), WildcardPat(WildcardPat), } +impl Pat { + pub fn into_box_pat(self) -> Option { + if let Self::BoxPat(variant) = self { Some(variant) } else { None } + } + pub fn into_const_block_pat(self) -> Option { + if let Self::ConstBlockPat(variant) = self { Some(variant) } else { None } + } + pub fn into_ident_pat(self) -> Option { + if let Self::IdentPat(variant) = self { Some(variant) } else { None } + } + pub fn into_literal_pat(self) -> Option { + if let Self::LiteralPat(variant) = self { Some(variant) } else { None } + } + pub fn into_macro_pat(self) -> Option { + if let Self::MacroPat(variant) = self { Some(variant) } else { None } + } + pub fn into_or_pat(self) -> Option { + if let Self::OrPat(variant) = self { Some(variant) } else { None } + } + pub fn into_paren_pat(self) -> Option { + if let Self::ParenPat(variant) = self { Some(variant) } else { None } + } + pub fn into_path_pat(self) -> Option { + if let Self::PathPat(variant) = self { Some(variant) } else { None } + } + pub fn into_range_pat(self) -> Option { + if let Self::RangePat(variant) = self { Some(variant) } else { None } + } + pub fn into_record_pat(self) -> Option { + if let Self::RecordPat(variant) = self { Some(variant) } else { None } + } + pub fn into_ref_pat(self) -> Option { + if let Self::RefPat(variant) = self { Some(variant) } else { None } + } + pub fn into_rest_pat(self) -> Option { + if let Self::RestPat(variant) = self { Some(variant) } else { None } + } + pub fn into_slice_pat(self) -> Option { + if let Self::SlicePat(variant) = self { Some(variant) } else { None } + } + pub fn into_tuple_pat(self) -> Option { + if let Self::TuplePat(variant) = self { Some(variant) } else { None } + } + pub fn into_tuple_struct_pat(self) -> Option { + if let Self::TupleStructPat(variant) = self { Some(variant) } else { None } + } + pub fn into_wildcard_pat(self) -> Option { + if let Self::WildcardPat(variant) = self { Some(variant) } else { None } + } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Stmt { @@ -2125,6 +2435,17 @@ pub enum Stmt { Item(Item), LetStmt(LetStmt), } +impl Stmt { + pub fn into_expr_stmt(self) -> Option { + if let Self::ExprStmt(variant) = self { Some(variant) } else { None } + } + pub fn into_item(self) -> Option { + if let Self::Item(variant) = self { Some(variant) } else { None } + } + pub fn into_let_stmt(self) -> Option { + if let Self::LetStmt(variant) = self { Some(variant) } else { None } + } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Type { @@ -2143,12 +2464,64 @@ pub enum Type { SliceType(SliceType), TupleType(TupleType), } +impl Type { + pub fn into_array_type(self) -> Option { + if let Self::ArrayType(variant) = self { Some(variant) } else { None } + } + pub fn into_dyn_trait_type(self) -> Option { + if let Self::DynTraitType(variant) = self { Some(variant) } else { None } + } + pub fn into_fn_ptr_type(self) -> Option { + if let Self::FnPtrType(variant) = self { Some(variant) } else { None } + } + pub fn into_for_type(self) -> Option { + if let Self::ForType(variant) = self { Some(variant) } else { None } + } + pub fn into_impl_trait_type(self) -> Option { + if let Self::ImplTraitType(variant) = self { Some(variant) } else { None } + } + pub fn into_infer_type(self) -> Option { + if let Self::InferType(variant) = self { Some(variant) } else { None } + } + pub fn into_macro_type(self) -> Option { + if let Self::MacroType(variant) = self { Some(variant) } else { None } + } + pub fn into_never_type(self) -> Option { + if let Self::NeverType(variant) = self { Some(variant) } else { None } + } + pub fn into_paren_type(self) -> Option { + if let Self::ParenType(variant) = self { Some(variant) } else { None } + } + pub fn into_path_type(self) -> Option { + if let Self::PathType(variant) = self { Some(variant) } else { None } + } + pub fn into_ptr_type(self) -> Option { + if let Self::PtrType(variant) = self { Some(variant) } else { None } + } + pub fn into_ref_type(self) -> Option { + if let Self::RefType(variant) = self { Some(variant) } else { None } + } + pub fn into_slice_type(self) -> Option { + if let Self::SliceType(variant) = self { Some(variant) } else { None } + } + pub fn into_tuple_type(self) -> Option { + if let Self::TupleType(variant) = self { Some(variant) } else { None } + } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum UseBoundGenericArg { Lifetime(Lifetime), NameRef(NameRef), } +impl UseBoundGenericArg { + pub fn into_lifetime(self) -> Option { + if let Self::Lifetime(variant) = self { Some(variant) } else { None } + } + pub fn into_name_ref(self) -> Option { + if let Self::NameRef(variant) = self { Some(variant) } else { None } + } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum VariantDef { @@ -2156,6 +2529,17 @@ pub enum VariantDef { Union(Union), Variant(Variant), } +impl VariantDef { + pub fn into_struct(self) -> Option { + if let Self::Struct(variant) = self { Some(variant) } else { None } + } + pub fn into_union(self) -> Option { + if let Self::Union(variant) = self { Some(variant) } else { None } + } + pub fn into_variant(self) -> Option { + if let Self::Variant(variant) = self { Some(variant) } else { None } + } +} impl ast::HasAttrs for VariantDef {} impl ast::HasDocComments for VariantDef {} impl ast::HasName for VariantDef {} diff --git a/xtask/src/codegen/grammar.rs b/xtask/src/codegen/grammar.rs index 9bd87a7ef5fe..9e73d1c29c14 100644 --- a/xtask/src/codegen/grammar.rs +++ b/xtask/src/codegen/grammar.rs @@ -250,6 +250,19 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String { let trait_name = format_ident!("{}", trait_name); quote!(impl ast::#trait_name for #name {}) }); + let cast_methods = variants.iter().map(|variant| { + let into_method = + format_ident!("into_{}", to_lower_snake_case(&variant.to_string())); + quote! { + pub fn #into_method(self) -> Option<#variant> { + if let Self::#variant(variant) = self { + Some(variant) + } else { + None + } + } + } + }); let ast_node = if en.name == "Stmt" { quote! {} @@ -290,6 +303,9 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String { #(#variants(#variants),)* } + impl #name { + #(#cast_methods)* + } #(#traits)* }, quote! {