From 3d28292157e1b6c9675ef64eddf53786c3e7dc5f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 29 Jul 2020 15:45:23 +0200 Subject: [PATCH] Switch to ungrammar from ast_src The primary advantage of ungrammar is that it (eventually) allows one to describe concrete syntax tree structure -- with alternatives and specific sequence of tokens & nodes. That should be re-usable for: * generate `make` calls * Rust reference * Hypothetical parser's evented API We loose doc comments for the time being unfortunately. I don't think we should add support for doc comments to ungrammar -- they'll make grammar file hard to read. We might supply docs as out-of band info, or maybe just via a reference, but we'll think about that once things are no longer in flux --- Cargo.lock | 7 + crates/ra_hir_def/src/type_ref.rs | 2 +- crates/ra_syntax/src/ast/expr_ext.rs | 2 + crates/ra_syntax/src/ast/generated/nodes.rs | 4614 +++++++------------ crates/ra_syntax/src/ast/node_ext.rs | 16 + xtask/Cargo.toml | 9 +- xtask/src/ast_src.rs | 1984 +------- xtask/src/codegen/gen_syntax.rs | 224 +- xtask/src/codegen/rust.ungram | 529 +++ 9 files changed, 2393 insertions(+), 4994 deletions(-) create mode 100644 xtask/src/codegen/rust.ungram diff --git a/Cargo.lock b/Cargo.lock index ff225399e0..b7a9516e3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1749,6 +1749,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "ungrammar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee12e4891ab3acc2d95d5023022ace22020247bb8a8d1ece875a443f7dab37d" + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -1893,5 +1899,6 @@ dependencies = [ "pico-args", "proc-macro2", "quote", + "ungrammar", "walkdir", ] diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs index e90b2a0b92..970fc9af54 100644 --- a/crates/ra_hir_def/src/type_ref.rs +++ b/crates/ra_hir_def/src/type_ref.rs @@ -1,7 +1,7 @@ //! HIR for references to types. Paths in these are not yet resolved. They can //! be directly created from an ast::TypeRef, without further queries. -use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner}; +use ra_syntax::ast::{self, TypeAscriptionOwner}; use crate::{body::LowerCtx, path::Path}; diff --git a/crates/ra_syntax/src/ast/expr_ext.rs b/crates/ra_syntax/src/ast/expr_ext.rs index db5438d687..69c85c809d 100644 --- a/crates/ra_syntax/src/ast/expr_ext.rs +++ b/crates/ra_syntax/src/ast/expr_ext.rs @@ -7,6 +7,8 @@ use crate::{ SyntaxToken, T, }; +impl ast::AttrsOwner for ast::Expr {} + impl ast::Expr { pub fn is_block_like(&self) -> bool { match self { diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs index 1fe5f450a4..b2d108a7ca 100644 --- a/crates/ra_syntax/src/ast/generated/nodes.rs +++ b/crates/ra_syntax/src/ast/generated/nodes.rs @@ -5,1882 +5,13 @@ use crate::{ SyntaxKind::{self, *}, SyntaxNode, SyntaxToken, T, }; -/// The entire Rust source file. Includes all top-level inner attributes and module items. -/// -/// [Reference](https://doc.rust-lang.org/reference/crates-and-source-files.html) #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct SourceFile { pub(crate) syntax: SyntaxNode, } -impl ast::ModuleItemOwner for SourceFile {} impl ast::AttrsOwner for SourceFile {} -impl ast::DocCommentsOwner for SourceFile {} +impl ast::ModuleItemOwner for SourceFile {} impl SourceFile {} -/// Function definition either with body or not. -/// Includes all of its attributes and doc comments. -/// -/// ``` -/// ❰ -/// /// Docs -/// #[attr] -/// pub extern "C" fn foo(#[attr] Patern {p}: Pattern) -> u32 -/// where -/// T: Debug -/// { -/// 42 -/// } -/// ❱ -/// -/// extern "C" { -/// ❰ fn fn_decl(also_variadic_ffi: u32, ...) -> u32; ❱ -/// } -/// ``` -/// -/// - [Reference](https://doc.rust-lang.org/reference/items/functions.html) -/// - [Nomicon](https://doc.rust-lang.org/nomicon/ffi.html#variadic-functions) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct FnDef { - pub(crate) syntax: SyntaxNode, -} -impl ast::VisibilityOwner for FnDef {} -impl ast::NameOwner for FnDef {} -impl ast::TypeParamsOwner for FnDef {} -impl ast::DocCommentsOwner for FnDef {} -impl ast::AttrsOwner for FnDef {} -impl FnDef { - pub fn abi(&self) -> Option { support::child(&self.syntax) } - pub fn const_token(&self) -> Option { support::token(&self.syntax, T![const]) } - pub fn default_token(&self) -> Option { support::token(&self.syntax, T![default]) } - pub fn async_token(&self) -> Option { support::token(&self.syntax, T![async]) } - pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } - pub fn fn_token(&self) -> Option { support::token(&self.syntax, T![fn]) } - pub fn param_list(&self) -> Option { support::child(&self.syntax) } - pub fn ret_type(&self) -> Option { support::child(&self.syntax) } - pub fn body(&self) -> Option { support::child(&self.syntax) } - pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } -} -/// Return type annotation. -/// -/// ``` -/// fn foo(a: u32) ❰ -> Option ❱ { Some(a) } -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/functions.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct RetType { - pub(crate) syntax: SyntaxNode, -} -impl RetType { - pub fn thin_arrow_token(&self) -> Option { support::token(&self.syntax, T![->]) } - pub fn type_ref(&self) -> Option { support::child(&self.syntax) } -} -/// Struct definition. -/// Includes all of its attributes and doc comments. -/// -/// ``` -/// ❰ -/// /// Docs -/// #[attr] -/// struct Foo where T: Debug { -/// /// Docs -/// #[attr] -/// pub a: u32, -/// b: T, -/// } -/// ❱ -/// -/// ❰ struct Foo; ❱ -/// ❰ struct Foo(#[attr] T) where T: Debug; ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/structs.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct StructDef { - pub(crate) syntax: SyntaxNode, -} -impl ast::VisibilityOwner for StructDef {} -impl ast::NameOwner for StructDef {} -impl ast::TypeParamsOwner for StructDef {} -impl ast::AttrsOwner for StructDef {} -impl ast::DocCommentsOwner for StructDef {} -impl StructDef { - pub fn struct_token(&self) -> Option { support::token(&self.syntax, T![struct]) } - pub fn field_def_list(&self) -> Option { support::child(&self.syntax) } - pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } -} -/// Union definition. -/// Includes all of its attributes and doc comments. -/// -/// ``` -/// ❰ -/// /// Docs -/// #[attr] -/// pub union Foo where T: Debug { -/// /// Docs -/// #[attr] -/// a: T, -/// b: u32, -/// } -/// ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/unions.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct UnionDef { - pub(crate) syntax: SyntaxNode, -} -impl ast::VisibilityOwner for UnionDef {} -impl ast::NameOwner for UnionDef {} -impl ast::TypeParamsOwner for UnionDef {} -impl ast::AttrsOwner for UnionDef {} -impl ast::DocCommentsOwner for UnionDef {} -impl UnionDef { - pub fn union_token(&self) -> Option { support::token(&self.syntax, T![union]) } - pub fn record_field_def_list(&self) -> Option { - support::child(&self.syntax) - } -} -/// Record field definition list including enclosing curly braces. -/// -/// ``` -/// struct Foo // same for union -/// ❰ -/// { -/// a: u32, -/// b: bool, -/// } -/// ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/structs.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct RecordFieldDefList { - pub(crate) syntax: SyntaxNode, -} -impl RecordFieldDefList { - pub fn l_curly_token(&self) -> Option { support::token(&self.syntax, T!['{']) } - pub fn fields(&self) -> AstChildren { support::children(&self.syntax) } - pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } -} -/// Record field definition including its attributes and doc comments. -/// -/// ` `` -/// same for union -/// struct Foo { -/// ❰ -/// /// Docs -/// #[attr] -/// pub a: u32 -/// ❱ -/// -/// ❰ b: bool ❱ -/// } -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/structs.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct RecordFieldDef { - pub(crate) syntax: SyntaxNode, -} -impl ast::VisibilityOwner for RecordFieldDef {} -impl ast::NameOwner for RecordFieldDef {} -impl ast::AttrsOwner for RecordFieldDef {} -impl ast::DocCommentsOwner for RecordFieldDef {} -impl ast::TypeAscriptionOwner for RecordFieldDef {} -impl RecordFieldDef {} -/// Tuple field definition list including enclosing parens. -/// -/// ``` -/// struct Foo ❰ (u32, String, Vec) ❱; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/structs.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TupleFieldDefList { - pub(crate) syntax: SyntaxNode, -} -impl TupleFieldDefList { - pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } - pub fn fields(&self) -> AstChildren { support::children(&self.syntax) } - pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } -} -/// Tuple field definition including its attributes. -/// -/// ``` -/// struct Foo(❰ #[attr] u32 ❱); -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/structs.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TupleFieldDef { - pub(crate) syntax: SyntaxNode, -} -impl ast::VisibilityOwner for TupleFieldDef {} -impl ast::AttrsOwner for TupleFieldDef {} -impl TupleFieldDef { - pub fn type_ref(&self) -> Option { support::child(&self.syntax) } -} -/// Enum definition. -/// Includes all of its attributes and doc comments. -/// -/// ``` -/// ❰ -/// /// Docs -/// #[attr] -/// pub enum Foo where T: Debug { -/// /// Docs -/// #[attr] -/// Bar, -/// Baz(#[attr] u32), -/// Bruh { -/// a: u32, -/// /// Docs -/// #[attr] -/// b: T, -/// } -/// } -/// ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct EnumDef { - pub(crate) syntax: SyntaxNode, -} -impl ast::VisibilityOwner for EnumDef {} -impl ast::NameOwner for EnumDef {} -impl ast::TypeParamsOwner for EnumDef {} -impl ast::AttrsOwner for EnumDef {} -impl ast::DocCommentsOwner for EnumDef {} -impl EnumDef { - pub fn enum_token(&self) -> Option { support::token(&self.syntax, T![enum]) } - pub fn variant_list(&self) -> Option { support::child(&self.syntax) } -} -/// Enum variant definition list including enclosing curly braces. -/// -/// ``` -/// enum Foo -/// ❰ -/// { -/// Bar, -/// Baz(u32), -/// Bruh { -/// a: u32 -/// } -/// } -/// ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct EnumVariantList { - pub(crate) syntax: SyntaxNode, -} -impl EnumVariantList { - pub fn l_curly_token(&self) -> Option { support::token(&self.syntax, T!['{']) } - pub fn variants(&self) -> AstChildren { support::children(&self.syntax) } - pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } -} -/// Enum variant definition including its attributes and discriminant value definition. -/// -/// ``` -/// enum Foo { -/// ❰ -/// /// Docs -/// #[attr] -/// Bar -/// ❱ -/// -/// // same for tuple and record variants -/// } -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct EnumVariant { - pub(crate) syntax: SyntaxNode, -} -impl ast::VisibilityOwner for EnumVariant {} -impl ast::NameOwner for EnumVariant {} -impl ast::DocCommentsOwner for EnumVariant {} -impl ast::AttrsOwner for EnumVariant {} -impl EnumVariant { - pub fn field_def_list(&self) -> Option { support::child(&self.syntax) } - pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } - pub fn expr(&self) -> Option { support::child(&self.syntax) } -} -/// Trait definition. -/// Includes all of its attributes and doc comments. -/// -/// ``` -/// ❰ -/// /// Docs -/// #[attr] -/// pub unsafe trait Foo: Debug where T: Debug { -/// // ... -/// } -/// ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/traits.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TraitDef { - pub(crate) syntax: SyntaxNode, -} -impl ast::VisibilityOwner for TraitDef {} -impl ast::NameOwner for TraitDef {} -impl ast::AttrsOwner for TraitDef {} -impl ast::DocCommentsOwner for TraitDef {} -impl ast::TypeParamsOwner for TraitDef {} -impl ast::TypeBoundsOwner for TraitDef {} -impl TraitDef { - pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } - pub fn auto_token(&self) -> Option { support::token(&self.syntax, T![auto]) } - pub fn trait_token(&self) -> Option { support::token(&self.syntax, T![trait]) } - pub fn item_list(&self) -> Option { support::child(&self.syntax) } -} -/// Module definition either with body or not. -/// Includes all of its inner and outer attributes, module items, doc comments. -/// -/// ``` -/// ❰ -/// /// Docs -/// #[attr] -/// pub mod foo; -/// ❱ -/// -/// ❰ -/// /// Docs -/// #[attr] -/// pub mod bar { -/// //! Inner docs -/// #![inner_attr] -/// } -/// ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/modules.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Module { - pub(crate) syntax: SyntaxNode, -} -impl ast::VisibilityOwner for Module {} -impl ast::NameOwner for Module {} -impl ast::AttrsOwner for Module {} -impl ast::DocCommentsOwner for Module {} -impl Module { - pub fn mod_token(&self) -> Option { support::token(&self.syntax, T![mod]) } - pub fn item_list(&self) -> Option { support::child(&self.syntax) } - pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } -} -/// Item defintion list. -/// This is used for both top-level items and impl block items. -/// -/// ``` -/// ❰ -/// fn foo {} -/// struct Bar; -/// enum Baz; -/// trait Bruh; -/// const BRUUH: u32 = 42; -/// ❱ -/// -/// impl Foo -/// ❰ -/// { -/// fn bar() {} -/// const BAZ: u32 = 42; -/// } -/// ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ItemList { - pub(crate) syntax: SyntaxNode, -} -impl ast::ModuleItemOwner for ItemList {} -impl ItemList { - pub fn l_curly_token(&self) -> Option { support::token(&self.syntax, T!['{']) } - pub fn assoc_items(&self) -> AstChildren { support::children(&self.syntax) } - pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } -} -/// Constant variable definition. -/// Includes all of its attributes and doc comments. -/// -/// ``` -/// ❰ -/// /// Docs -/// #[attr] -/// pub const FOO: u32 = 42; -/// ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/constant-items.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ConstDef { - pub(crate) syntax: SyntaxNode, -} -impl ast::VisibilityOwner for ConstDef {} -impl ast::NameOwner for ConstDef {} -impl ast::TypeParamsOwner for ConstDef {} -impl ast::AttrsOwner for ConstDef {} -impl ast::DocCommentsOwner for ConstDef {} -impl ast::TypeAscriptionOwner for ConstDef {} -impl ConstDef { - pub fn default_token(&self) -> Option { support::token(&self.syntax, T![default]) } - pub fn const_token(&self) -> Option { support::token(&self.syntax, T![const]) } - pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } - pub fn body(&self) -> Option { support::child(&self.syntax) } - pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } -} -/// Static variable definition. -/// Includes all of its attributes and doc comments. -/// -/// ``` -/// ❰ -/// /// Docs -/// #[attr] -/// pub static mut FOO: u32 = 42; -/// ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/static-items.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct StaticDef { - pub(crate) syntax: SyntaxNode, -} -impl ast::VisibilityOwner for StaticDef {} -impl ast::NameOwner for StaticDef {} -impl ast::TypeParamsOwner for StaticDef {} -impl ast::AttrsOwner for StaticDef {} -impl ast::DocCommentsOwner for StaticDef {} -impl ast::TypeAscriptionOwner for StaticDef {} -impl StaticDef { - pub fn static_token(&self) -> Option { support::token(&self.syntax, T![static]) } - pub fn mut_token(&self) -> Option { support::token(&self.syntax, T![mut]) } - pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } - pub fn body(&self) -> Option { support::child(&self.syntax) } - pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } -} -/// Type alias definition. -/// Includes associated type clauses with type bounds. -/// -/// ``` -/// ❰ -/// /// Docs -/// #[attr] -/// pub type Foo where T: Debug = T; -/// ❱ -/// -/// trait Bar { -/// ❰ type Baz: Debug; ❱ -/// ❰ type Bruh = String; ❱ -/// ❰ type Bruuh: Debug = u32; ❱ -/// } -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/type-aliases.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TypeAliasDef { - pub(crate) syntax: SyntaxNode, -} -impl ast::VisibilityOwner for TypeAliasDef {} -impl ast::NameOwner for TypeAliasDef {} -impl ast::TypeParamsOwner for TypeAliasDef {} -impl ast::AttrsOwner for TypeAliasDef {} -impl ast::DocCommentsOwner for TypeAliasDef {} -impl ast::TypeBoundsOwner for TypeAliasDef {} -impl TypeAliasDef { - pub fn default_token(&self) -> Option { support::token(&self.syntax, T![default]) } - pub fn type_token(&self) -> Option { support::token(&self.syntax, T![type]) } - pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } - pub fn type_ref(&self) -> Option { support::child(&self.syntax) } - pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } -} -/// Inherent and trait impl definition. -/// Includes all of its inner and outer attributes. -/// -/// ``` -/// ❰ -/// #[attr] -/// unsafe impl const !Foo for Bar where T: Debug { -/// #![inner_attr] -/// // ... -/// } -/// ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/items/implementations.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ImplDef { - pub(crate) syntax: SyntaxNode, -} -impl ast::TypeParamsOwner for ImplDef {} -impl ast::AttrsOwner for ImplDef {} -impl ast::DocCommentsOwner for ImplDef {} -impl ImplDef { - pub fn default_token(&self) -> Option { support::token(&self.syntax, T![default]) } - pub fn const_token(&self) -> Option { support::token(&self.syntax, T![const]) } - pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } - pub fn impl_token(&self) -> Option { support::token(&self.syntax, T![impl]) } - pub fn excl_token(&self) -> Option { support::token(&self.syntax, T![!]) } - pub fn for_token(&self) -> Option { support::token(&self.syntax, T![for]) } - pub fn item_list(&self) -> Option { support::child(&self.syntax) } -} -/// Parenthesized type reference. -/// Note: parens are only used for grouping, this is not a tuple type. -/// -/// ``` -/// // This is effectively just `u32`. -/// // Single-item tuple must be defined with a trailing comma: `(u32,)` -/// type Foo = ❰ (u32) ❱; -/// -/// let bar: &'static ❰ (dyn Debug) ❱ = "bruh"; -/// ``` -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ParenType { - pub(crate) syntax: SyntaxNode, -} -impl ParenType { - pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } - pub fn type_ref(&self) -> Option { support::child(&self.syntax) } - pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } -} -/// Unnamed tuple type. -/// -/// ``` -/// let foo: ❰ (u32, bool) ❱ = (42, true); -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/types/tuple.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TupleType { - pub(crate) syntax: SyntaxNode, -} -impl TupleType { - pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } - pub fn fields(&self) -> AstChildren { support::children(&self.syntax) } - pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } -} -/// The never type (i.e. the exclamation point). -/// -/// ``` -/// type T = ❰ ! ❱; -/// -/// fn no_return() -> ❰ ! ❱ { -/// loop {} -/// } -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/types/never.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct NeverType { - pub(crate) syntax: SyntaxNode, -} -impl NeverType { - pub fn excl_token(&self) -> Option { support::token(&self.syntax, T![!]) } -} -/// Path to a type. -/// Includes single identifier type names and elaborate paths with -/// generic parameters. -/// -/// ``` -/// type Foo = ❰ String ❱; -/// type Bar = ❰ std::vec::Vec ❱; -/// type Baz = ❰ ::bruh::::Item ❱; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/paths.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct PathType { - pub(crate) syntax: SyntaxNode, -} -impl PathType { - pub fn path(&self) -> Option { support::child(&self.syntax) } -} -/// Raw pointer type. -/// -/// ``` -/// type Foo = ❰ *const u32 ❱; -/// type Bar = ❰ *mut u32 ❱; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/types/pointer.html#raw-pointers-const-and-mut) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct PointerType { - pub(crate) syntax: SyntaxNode, -} -impl PointerType { - pub fn star_token(&self) -> Option { support::token(&self.syntax, T![*]) } - pub fn const_token(&self) -> Option { support::token(&self.syntax, T![const]) } - pub fn mut_token(&self) -> Option { support::token(&self.syntax, T![mut]) } - pub fn type_ref(&self) -> Option { support::child(&self.syntax) } -} -/// Array type. -/// -/// ``` -/// type Foo = ❰ [u32; 24 - 3] ❱; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/types/array.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ArrayType { - pub(crate) syntax: SyntaxNode, -} -impl ArrayType { - pub fn l_brack_token(&self) -> Option { support::token(&self.syntax, T!['[']) } - pub fn type_ref(&self) -> Option { support::child(&self.syntax) } - pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } - pub fn expr(&self) -> Option { support::child(&self.syntax) } - pub fn r_brack_token(&self) -> Option { support::token(&self.syntax, T![']']) } -} -/// Slice type. -/// -/// ``` -/// type Foo = ❰ [u8] ❱; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/types/slice.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct SliceType { - pub(crate) syntax: SyntaxNode, -} -impl SliceType { - pub fn l_brack_token(&self) -> Option { support::token(&self.syntax, T!['[']) } - pub fn type_ref(&self) -> Option { support::child(&self.syntax) } - pub fn r_brack_token(&self) -> Option { support::token(&self.syntax, T![']']) } -} -/// Reference type. -/// -/// ``` -/// type Foo = ❰ &'static str ❱; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/types/pointer.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ReferenceType { - pub(crate) syntax: SyntaxNode, -} -impl ReferenceType { - pub fn amp_token(&self) -> Option { support::token(&self.syntax, T![&]) } - pub fn lifetime_token(&self) -> Option { - support::token(&self.syntax, T![lifetime]) - } - pub fn mut_token(&self) -> Option { support::token(&self.syntax, T![mut]) } - pub fn type_ref(&self) -> Option { support::child(&self.syntax) } -} -/// Placeholder type (i.e. the underscore). -/// -/// ``` -/// let foo: ❰ _ ❱ = 42_u32; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/types/inferred.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct PlaceholderType { - pub(crate) syntax: SyntaxNode, -} -impl PlaceholderType { - pub fn underscore_token(&self) -> Option { support::token(&self.syntax, T![_]) } -} -/// Function pointer type (not to be confused with `Fn*` family of traits). -/// -/// ``` -/// type Foo = ❰ async fn(#[attr] u32, named: bool) -> u32 ❱; -/// -/// type Bar = ❰ extern "C" fn(variadic: u32, #[attr] ...) ❱; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/types/function-pointer.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct FnPointerType { - pub(crate) syntax: SyntaxNode, -} -impl FnPointerType { - pub fn abi(&self) -> Option { support::child(&self.syntax) } - pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } - pub fn fn_token(&self) -> Option { support::token(&self.syntax, T![fn]) } - pub fn param_list(&self) -> Option { support::child(&self.syntax) } - pub fn ret_type(&self) -> Option { support::child(&self.syntax) } -} -/// Higher order type. -/// -/// ``` -/// type Foo = ❰ for<'a> fn(&'a str) ❱; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/nomicon/hrtb.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ForType { - pub(crate) syntax: SyntaxNode, -} -impl ForType { - pub fn for_token(&self) -> Option { support::token(&self.syntax, T![for]) } - pub fn type_param_list(&self) -> Option { support::child(&self.syntax) } - pub fn type_ref(&self) -> Option { support::child(&self.syntax) } -} -/// Opaque `impl Trait` type. -/// -/// ``` -/// fn foo(bar: ❰ impl Debug + Eq ❱) {} -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/types/impl-trait.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ImplTraitType { - pub(crate) syntax: SyntaxNode, -} -impl ast::TypeBoundsOwner for ImplTraitType {} -impl ImplTraitType { - pub fn impl_token(&self) -> Option { support::token(&self.syntax, T![impl]) } -} -/// Trait object type. -/// -/// ``` -/// type Foo = ❰ dyn Debug ❱; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/types/trait-object.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct DynTraitType { - pub(crate) syntax: SyntaxNode, -} -impl ast::TypeBoundsOwner for DynTraitType {} -impl DynTraitType { - pub fn dyn_token(&self) -> Option { support::token(&self.syntax, T![dyn]) } -} -/// Tuple literal. -/// -/// ``` -/// ❰ (42, true) ❱; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/expressions/tuple-expr.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TupleExpr { - pub(crate) syntax: SyntaxNode, -} -impl ast::AttrsOwner for TupleExpr {} -impl TupleExpr { - pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } - pub fn exprs(&self) -> AstChildren { support::children(&self.syntax) } - pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } -} -/// Array literal. -/// -/// ``` -/// ❰ [#![inner_attr] true, false, true] ❱; -/// -/// ❰ ["baz"; 24] ❱; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ArrayExpr { - pub(crate) syntax: SyntaxNode, -} -impl ast::AttrsOwner for ArrayExpr {} -impl ArrayExpr { - pub fn l_brack_token(&self) -> Option { support::token(&self.syntax, T!['[']) } - pub fn exprs(&self) -> AstChildren { support::children(&self.syntax) } - pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } - pub fn r_brack_token(&self) -> Option { support::token(&self.syntax, T![']']) } -} -/// Parenthesized expression. -/// Note: parens are only used for grouping, this is not a tuple literal. -/// -/// ``` -/// ❰ (#![inner_attr] 2 + 2) ❱ * 2; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/expressions/grouped-expr.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ParenExpr { - pub(crate) syntax: SyntaxNode, -} -impl ast::AttrsOwner for ParenExpr {} -impl ParenExpr { - pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } - pub fn expr(&self) -> Option { support::child(&self.syntax) } - pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } -} -/// Path to a symbol in expression context. -/// Includes single identifier variable names and elaborate paths with -/// generic parameters. -/// -/// ``` -/// ❰ Some:: ❱; -/// ❰ foo ❱ + 42; -/// ❰ Vec::::push ❱; -/// ❰ <[i32]>::reverse ❱; -/// ❰ >::borrow ❱; -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/expressions/path-expr.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct PathExpr { - pub(crate) syntax: SyntaxNode, -} -impl PathExpr { - pub fn path(&self) -> Option { support::child(&self.syntax) } -} -/// Anonymous callable object literal a.k.a. closure, lambda or functor. -/// -/// ``` -/// ❰ || 42 ❱; -/// ❰ |a: u32| val + 1 ❱; -/// ❰ async |#[attr] Pattern(_): Pattern| { bar } ❱; -/// ❰ move || baz ❱; -/// ❰ || -> u32 { closure_with_ret_type_annotation_requires_block_expr } ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/expressions/closure-expr.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct LambdaExpr { - pub(crate) syntax: SyntaxNode, -} -impl ast::AttrsOwner for LambdaExpr {} -impl LambdaExpr { - pub fn static_token(&self) -> Option { support::token(&self.syntax, T![static]) } - pub fn async_token(&self) -> Option { support::token(&self.syntax, T![async]) } - pub fn move_token(&self) -> Option { support::token(&self.syntax, T![move]) } - pub fn param_list(&self) -> Option { support::child(&self.syntax) } - pub fn ret_type(&self) -> Option { support::child(&self.syntax) } - pub fn body(&self) -> Option { support::child(&self.syntax) } -} -/// If expression. Includes both regular `if` and `if let` forms. -/// Beware that `else if` is a special case syntax sugar, because in general -/// there has to be block expression after `else`. -/// -/// ``` -/// ❰ if bool_cond { 42 } ❱ -/// ❰ if bool_cond { 42 } else { 24 } ❱ -/// ❰ if bool_cond { 42 } else if bool_cond2 { 42 } ❱ -/// -/// ❰ -/// if let Pattern(foo) = bar { -/// foo -/// } else { -/// panic!(); -/// } -/// ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/expressions/if-expr.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct IfExpr { - pub(crate) syntax: SyntaxNode, -} -impl ast::AttrsOwner for IfExpr {} -impl IfExpr { - pub fn if_token(&self) -> Option { support::token(&self.syntax, T![if]) } - pub fn condition(&self) -> Option { support::child(&self.syntax) } -} -/// Unconditional loop expression. -/// -/// ``` -/// ❰ -/// loop { -/// // yeah, it's that simple... -/// } -/// ❱ -/// ``` -/// -/// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct LoopExpr { - pub(crate) syntax: SyntaxNode, -} -impl ast::AttrsOwner for LoopExpr {} -impl ast::LoopBodyOwner for LoopExpr {} -impl LoopExpr { - pub fn loop_token(&self) -> Option { support::token(&self.syntax, T![loop]) } -} -/// Block expression with an optional prefix (label, try ketword, -/// unsafe keyword, async keyword...). -/// -/// ``` -/// ❰ -/// 'label: try { -/// None? -/// } -/// ❱ -/// ``` -/// -/// - [try block](https://doc.rust-lang.org/unstable-book/language-features/try-blocks.html) -/// - [unsafe block](https://doc.rust-lang.org/reference/expressions/block-expr.html#unsafe-blocks) -/// - [async block](https://doc.rust-lang.org/reference/expressions/block-expr.html#async-blocks) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct EffectExpr { - pub(crate) syntax: SyntaxNode, -} -impl ast::AttrsOwner for EffectExpr {} -impl EffectExpr { - pub fn label(&self) -> Option