diff options
| author | Aleksey Kladov <aleksey.kladov@gmail.com> | 2020-08-12 18:26:51 +0200 |
|---|---|---|
| committer | Aleksey Kladov <aleksey.kladov@gmail.com> | 2020-08-12 18:30:53 +0200 |
| commit | a1c187eef3ba08076aedb5154929f7eda8d1b424 (patch) | |
| tree | 9d898eb9600b0c36a74e4f95238f679c683fa566 /crates/syntax/src/ast | |
| parent | 3d6889cba72a9d02199f7adaa2ecc69bc30af834 (diff) | |
| download | rust-a1c187eef3ba08076aedb5154929f7eda8d1b424.tar.gz rust-a1c187eef3ba08076aedb5154929f7eda8d1b424.zip | |
Rename ra_syntax -> syntax
Diffstat (limited to 'crates/syntax/src/ast')
| -rw-r--r-- | crates/syntax/src/ast/edit.rs | 642 | ||||
| -rw-r--r-- | crates/syntax/src/ast/expr_ext.rs | 418 | ||||
| -rw-r--r-- | crates/syntax/src/ast/generated.rs | 41 | ||||
| -rw-r--r-- | crates/syntax/src/ast/generated/nodes.rs | 4067 | ||||
| -rw-r--r-- | crates/syntax/src/ast/generated/tokens.rs | 91 | ||||
| -rw-r--r-- | crates/syntax/src/ast/make.rs | 392 | ||||
| -rw-r--r-- | crates/syntax/src/ast/node_ext.rs | 485 | ||||
| -rw-r--r-- | crates/syntax/src/ast/token_ext.rs | 538 | ||||
| -rw-r--r-- | crates/syntax/src/ast/traits.rs | 141 |
9 files changed, 6815 insertions, 0 deletions
diff --git a/crates/syntax/src/ast/edit.rs b/crates/syntax/src/ast/edit.rs new file mode 100644 index 00000000000..5ed123f91fe --- /dev/null +++ b/crates/syntax/src/ast/edit.rs @@ -0,0 +1,642 @@ +//! This module contains functions for editing syntax trees. As the trees are +//! immutable, all function here return a fresh copy of the tree, instead of +//! doing an in-place modification. +use std::{ + fmt, iter, + ops::{self, RangeInclusive}, +}; + +use arrayvec::ArrayVec; + +use crate::{ + algo::{self, neighbor, SyntaxRewriter}, + ast::{ + self, + make::{self, tokens}, + AstNode, TypeBoundsOwner, + }, + AstToken, Direction, InsertPosition, SmolStr, SyntaxElement, SyntaxKind, + SyntaxKind::{ATTR, COMMENT, WHITESPACE}, + SyntaxNode, SyntaxToken, T, +}; + +impl ast::BinExpr { + #[must_use] + pub fn replace_op(&self, op: SyntaxKind) -> Option<ast::BinExpr> { + let op_node: SyntaxElement = self.op_details()?.0.into(); + let to_insert: Option<SyntaxElement> = Some(make::token(op).into()); + Some(self.replace_children(single_node(op_node), to_insert)) + } +} + +impl ast::Fn { + #[must_use] + pub fn with_body(&self, body: ast::BlockExpr) -> ast::Fn { + let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); + let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() { + old_body.syntax().clone().into() + } else if let Some(semi) = self.semicolon_token() { + to_insert.push(make::tokens::single_space().into()); + semi.into() + } else { + to_insert.push(make::tokens::single_space().into()); + to_insert.push(body.syntax().clone().into()); + return self.insert_children(InsertPosition::Last, to_insert); + }; + to_insert.push(body.syntax().clone().into()); + self.replace_children(single_node(old_body_or_semi), to_insert) + } +} + +fn make_multiline<N>(node: N) -> N +where + N: AstNode + Clone, +{ + let l_curly = match node.syntax().children_with_tokens().find(|it| it.kind() == T!['{']) { + Some(it) => it, + None => return node, + }; + let sibling = match l_curly.next_sibling_or_token() { + Some(it) => it, + None => return node, + }; + let existing_ws = match sibling.as_token() { + None => None, + Some(tok) if tok.kind() != WHITESPACE => None, + Some(ws) => { + if ws.text().contains('\n') { + return node; + } + Some(ws.clone()) + } + }; + + let indent = leading_indent(node.syntax()).unwrap_or_default(); + let ws = tokens::WsBuilder::new(&format!("\n{}", indent)); + let to_insert = iter::once(ws.ws().into()); + match existing_ws { + None => node.insert_children(InsertPosition::After(l_curly), to_insert), + Some(ws) => node.replace_children(single_node(ws), to_insert), + } +} + +impl ast::AssocItemList { + #[must_use] + pub fn append_items( + &self, + items: impl IntoIterator<Item = ast::AssocItem>, + ) -> ast::AssocItemList { + let mut res = self.clone(); + if !self.syntax().text().contains_char('\n') { + res = make_multiline(res); + } + items.into_iter().for_each(|it| res = res.append_item(it)); + res + } + + #[must_use] + pub fn append_item(&self, item: ast::AssocItem) -> ast::AssocItemList { + let (indent, position) = match self.assoc_items().last() { + Some(it) => ( + leading_indent(it.syntax()).unwrap_or_default().to_string(), + InsertPosition::After(it.syntax().clone().into()), + ), + None => match self.l_curly_token() { + Some(it) => ( + " ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(), + InsertPosition::After(it.into()), + ), + None => return self.clone(), + }, + }; + let ws = tokens::WsBuilder::new(&format!("\n{}", indent)); + let to_insert: ArrayVec<[SyntaxElement; 2]> = + [ws.ws().into(), item.syntax().clone().into()].into(); + self.insert_children(position, to_insert) + } +} + +impl ast::RecordExprFieldList { + #[must_use] + pub fn append_field(&self, field: &ast::RecordExprField) -> ast::RecordExprFieldList { + self.insert_field(InsertPosition::Last, field) + } + + #[must_use] + pub fn insert_field( + &self, + position: InsertPosition<&'_ ast::RecordExprField>, + field: &ast::RecordExprField, + ) -> ast::RecordExprFieldList { + let is_multiline = self.syntax().text().contains_char('\n'); + let ws; + let space = if is_multiline { + ws = tokens::WsBuilder::new(&format!( + "\n{} ", + leading_indent(self.syntax()).unwrap_or_default() + )); + ws.ws() + } else { + tokens::single_space() + }; + + let mut to_insert: ArrayVec<[SyntaxElement; 4]> = ArrayVec::new(); + to_insert.push(space.into()); + to_insert.push(field.syntax().clone().into()); + to_insert.push(make::token(T![,]).into()); + + macro_rules! after_l_curly { + () => {{ + let anchor = match self.l_curly_token() { + Some(it) => it.into(), + None => return self.clone(), + }; + InsertPosition::After(anchor) + }}; + } + + macro_rules! after_field { + ($anchor:expr) => { + if let Some(comma) = $anchor + .syntax() + .siblings_with_tokens(Direction::Next) + .find(|it| it.kind() == T![,]) + { + InsertPosition::After(comma) + } else { + to_insert.insert(0, make::token(T![,]).into()); + InsertPosition::After($anchor.syntax().clone().into()) + } + }; + }; + + let position = match position { + InsertPosition::First => after_l_curly!(), + InsertPosition::Last => { + if !is_multiline { + // don't insert comma before curly + to_insert.pop(); + } + match self.fields().last() { + Some(it) => after_field!(it), + None => after_l_curly!(), + } + } + InsertPosition::Before(anchor) => { + InsertPosition::Before(anchor.syntax().clone().into()) + } + InsertPosition::After(anchor) => after_field!(anchor), + }; + + self.insert_children(position, to_insert) + } +} + +impl ast::TypeAlias { + #[must_use] + pub fn remove_bounds(&self) -> ast::TypeAlias { + let colon = match self.colon_token() { + Some(it) => it, + None => return self.clone(), + }; + let end = match self.type_bound_list() { + Some(it) => it.syntax().clone().into(), + None => colon.clone().into(), + }; + self.replace_children(colon.into()..=end, iter::empty()) + } +} + +impl ast::TypeParam { + #[must_use] + pub fn remove_bounds(&self) -> ast::TypeParam { + let colon = match self.colon_token() { + Some(it) => it, + None => return self.clone(), + }; + let end = match self.type_bound_list() { + Some(it) => it.syntax().clone().into(), + None => colon.clone().into(), + }; + self.replace_children(colon.into()..=end, iter::empty()) + } +} + +impl ast::Path { + #[must_use] + pub fn with_segment(&self, segment: ast::PathSegment) -> ast::Path { + if let Some(old) = self.segment() { + return self.replace_children( + single_node(old.syntax().clone()), + iter::once(segment.syntax().clone().into()), + ); + } + self.clone() + } +} + +impl ast::PathSegment { + #[must_use] + pub fn with_type_args(&self, type_args: ast::GenericArgList) -> ast::PathSegment { + self._with_type_args(type_args, false) + } + + #[must_use] + pub fn with_turbo_fish(&self, type_args: ast::GenericArgList) -> ast::PathSegment { + self._with_type_args(type_args, true) + } + + fn _with_type_args(&self, type_args: ast::GenericArgList, turbo: bool) -> ast::PathSegment { + if let Some(old) = self.generic_arg_list() { + return self.replace_children( + single_node(old.syntax().clone()), + iter::once(type_args.syntax().clone().into()), + ); + } + let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); + if turbo { + to_insert.push(make::token(T![::]).into()); + } + to_insert.push(type_args.syntax().clone().into()); + self.insert_children(InsertPosition::Last, to_insert) + } +} + +impl ast::Use { + #[must_use] + pub fn with_use_tree(&self, use_tree: ast::UseTree) -> ast::Use { + if let Some(old) = self.use_tree() { + return self.replace_descendant(old, use_tree); + } + self.clone() + } + + pub fn remove(&self) -> SyntaxRewriter<'static> { + let mut res = SyntaxRewriter::default(); + res.delete(self.syntax()); + let next_ws = self + .syntax() + .next_sibling_or_token() + .and_then(|it| it.into_token()) + .and_then(ast::Whitespace::cast); + if let Some(next_ws) = next_ws { + let ws_text = next_ws.syntax().text(); + if ws_text.starts_with('\n') { + let rest = &ws_text[1..]; + if rest.is_empty() { + res.delete(next_ws.syntax()) + } else { + res.replace(next_ws.syntax(), &make::tokens::whitespace(rest)); + } + } + } + res + } +} + +impl ast::UseTree { + #[must_use] + pub fn with_path(&self, path: ast::Path) -> ast::UseTree { + if let Some(old) = self.path() { + return self.replace_descendant(old, path); + } + self.clone() + } + + #[must_use] + pub fn with_use_tree_list(&self, use_tree_list: ast::UseTreeList) -> ast::UseTree { + if let Some(old) = self.use_tree_list() { + return self.replace_descendant(old, use_tree_list); + } + self.clone() + } + + #[must_use] + pub fn split_prefix(&self, prefix: &ast::Path) -> ast::UseTree { + let suffix = match split_path_prefix(&prefix) { + Some(it) => it, + None => return self.clone(), + }; + let use_tree = make::use_tree( + suffix, + self.use_tree_list(), + self.rename(), + self.star_token().is_some(), + ); + let nested = make::use_tree_list(iter::once(use_tree)); + return make::use_tree(prefix.clone(), Some(nested), None, false); + + fn split_path_prefix(prefix: &ast::Path) -> Option<ast::Path> { + let parent = prefix.parent_path()?; + let segment = parent.segment()?; + if algo::has_errors(segment.syntax()) { + return None; + } + let mut res = make::path_unqualified(segment); + for p in iter::successors(parent.parent_path(), |it| it.parent_path()) { + res = make::path_qualified(res, p.segment()?); + } + Some(res) + } + } + + pub fn remove(&self) -> SyntaxRewriter<'static> { + let mut res = SyntaxRewriter::default(); + res.delete(self.syntax()); + for &dir in [Direction::Next, Direction::Prev].iter() { + if let Some(nb) = neighbor(self, dir) { + self.syntax() + .siblings_with_tokens(dir) + .skip(1) + .take_while(|it| it.as_node() != Some(nb.syntax())) + .for_each(|el| res.delete(&el)); + return res; + } + } + res + } +} + +impl ast::MatchArmList { + #[must_use] + pub fn append_arms(&self, items: impl IntoIterator<Item = ast::MatchArm>) -> ast::MatchArmList { + let mut res = self.clone(); + res = res.strip_if_only_whitespace(); + if !res.syntax().text().contains_char('\n') { + res = make_multiline(res); + } + items.into_iter().for_each(|it| res = res.append_arm(it)); + res + } + + fn strip_if_only_whitespace(&self) -> ast::MatchArmList { + let mut iter = self.syntax().children_with_tokens().skip_while(|it| it.kind() != T!['{']); + iter.next(); // Eat the curly + let mut inner = iter.take_while(|it| it.kind() != T!['}']); + if !inner.clone().all(|it| it.kind() == WHITESPACE) { + return self.clone(); + } + let start = match inner.next() { + Some(s) => s, + None => return self.clone(), + }; + let end = match inner.last() { + Some(s) => s, + None => start.clone(), + }; + self.replace_children(start..=end, &mut iter::empty()) + } + + #[must_use] + pub fn remove_placeholder(&self) -> ast::MatchArmList { + let placeholder = + self.arms().find(|arm| matches!(arm.pat(), Some(ast::Pat::WildcardPat(_)))); + if let Some(placeholder) = placeholder { + self.remove_arm(&placeholder) + } else { + self.clone() + } + } + + #[must_use] + fn remove_arm(&self, arm: &ast::MatchArm) -> ast::MatchArmList { + let start = arm.syntax().clone(); + let end = if let Some(comma) = start + .siblings_with_tokens(Direction::Next) + .skip(1) + .skip_while(|it| it.kind().is_trivia()) + .next() + .filter(|it| it.kind() == T![,]) + { + comma + } else { + start.clone().into() + }; + self.replace_children(start.into()..=end, None) + } + + #[must_use] + pub fn append_arm(&self, item: ast::MatchArm) -> ast::MatchArmList { + let r_curly = match self.syntax().children_with_tokens().find(|it| it.kind() == T!['}']) { + Some(t) => t, + None => return self.clone(), + }; + let position = InsertPosition::Before(r_curly.into()); + let arm_ws = tokens::WsBuilder::new(" "); + let match_indent = &leading_indent(self.syntax()).unwrap_or_default(); + let match_ws = tokens::WsBuilder::new(&format!("\n{}", match_indent)); + let to_insert: ArrayVec<[SyntaxElement; 3]> = + [arm_ws.ws().into(), item.syntax().clone().into(), match_ws.ws().into()].into(); + self.insert_children(position, to_insert) + } +} + +#[must_use] +pub fn remove_attrs_and_docs<N: ast::AttrsOwner>(node: &N) -> N { + N::cast(remove_attrs_and_docs_inner(node.syntax().clone())).unwrap() +} + +fn remove_attrs_and_docs_inner(mut node: SyntaxNode) -> SyntaxNode { + while let Some(start) = + node.children_with_tokens().find(|it| it.kind() == ATTR || it.kind() == COMMENT) + { + let end = match &start.next_sibling_or_token() { + Some(el) if el.kind() == WHITESPACE => el.clone(), + Some(_) | None => start.clone(), + }; + node = algo::replace_children(&node, start..=end, &mut iter::empty()); + } + node +} + +#[derive(Debug, Clone, Copy)] +pub struct IndentLevel(pub u8); + +impl From<u8> for IndentLevel { + fn from(level: u8) -> IndentLevel { + IndentLevel(level) + } +} + +impl fmt::Display for IndentLevel { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let spaces = " "; + let buf; + let len = self.0 as usize * 4; + let indent = if len <= spaces.len() { + &spaces[..len] + } else { + buf = iter::repeat(' ').take(len).collect::<String>(); + &buf + }; + fmt::Display::fmt(indent, f) + } +} + +impl ops::Add<u8> for IndentLevel { + type Output = IndentLevel; + fn add(self, rhs: u8) -> IndentLevel { + IndentLevel(self.0 + rhs) + } +} + +impl IndentLevel { + pub fn from_node(node: &SyntaxNode) -> IndentLevel { + let first_token = match node.first_token() { + Some(it) => it, + None => return IndentLevel(0), + }; + for ws in prev_tokens(first_token).filter_map(ast::Whitespace::cast) { + let text = ws.syntax().text(); + if let Some(pos) = text.rfind('\n') { + let level = text[pos + 1..].chars().count() / 4; + return IndentLevel(level as u8); + } + } + IndentLevel(0) + } + + /// XXX: this intentionally doesn't change the indent of the very first token. + /// Ie, in something like + /// ``` + /// fn foo() { + /// 92 + /// } + /// ``` + /// if you indent the block, the `{` token would stay put. + fn increase_indent(self, node: SyntaxNode) -> SyntaxNode { + let mut rewriter = SyntaxRewriter::default(); + node.descendants_with_tokens() + .filter_map(|el| el.into_token()) + .filter_map(ast::Whitespace::cast) + .filter(|ws| { + let text = ws.syntax().text(); + text.contains('\n') + }) + .for_each(|ws| { + let new_ws = make::tokens::whitespace(&format!("{}{}", ws.syntax(), self,)); + rewriter.replace(ws.syntax(), &new_ws) + }); + rewriter.rewrite(&node) + } + + fn decrease_indent(self, node: SyntaxNode) -> SyntaxNode { + let mut rewriter = SyntaxRewriter::default(); + node.descendants_with_tokens() + .filter_map(|el| el.into_token()) + .filter_map(ast::Whitespace::cast) + .filter(|ws| { + let text = ws.syntax().text(); + text.contains('\n') + }) + .for_each(|ws| { + let new_ws = make::tokens::whitespace( + &ws.syntax().text().replace(&format!("\n{}", self), "\n"), + ); + rewriter.replace(ws.syntax(), &new_ws) + }); + rewriter.rewrite(&node) + } +} + +// FIXME: replace usages with IndentLevel above +fn leading_indent(node: &SyntaxNode) -> Option<SmolStr> { + for token in prev_tokens(node.first_token()?) { + if let Some(ws) = ast::Whitespace::cast(token.clone()) { + let ws_text = ws.text(); + if let Some(pos) = ws_text.rfind('\n') { + return Some(ws_text[pos + 1..].into()); + } + } + if token.text().contains('\n') { + break; + } + } + None +} + +fn prev_tokens(token: SyntaxToken) -> impl Iterator<Item = SyntaxToken> { + iter::successors(Some(token), |token| token.prev_token()) +} + +pub trait AstNodeEdit: AstNode + Clone + Sized { + #[must_use] + fn insert_children( + &self, + position: InsertPosition<SyntaxElement>, + to_insert: impl IntoIterator<Item = SyntaxElement>, + ) -> Self { + let new_syntax = algo::insert_children(self.syntax(), position, to_insert); + Self::cast(new_syntax).unwrap() + } + + #[must_use] + fn replace_children( + &self, + to_replace: RangeInclusive<SyntaxElement>, + to_insert: impl IntoIterator<Item = SyntaxElement>, + ) -> Self { + let new_syntax = algo::replace_children(self.syntax(), to_replace, to_insert); + Self::cast(new_syntax).unwrap() + } + + #[must_use] + fn replace_descendant<D: AstNode>(&self, old: D, new: D) -> Self { + self.replace_descendants(iter::once((old, new))) + } + + #[must_use] + fn replace_descendants<D: AstNode>( + &self, + replacement_map: impl IntoIterator<Item = (D, D)>, + ) -> Self { + let mut rewriter = SyntaxRewriter::default(); + for (from, to) in replacement_map { + rewriter.replace(from.syntax(), to.syntax()) + } + rewriter.rewrite_ast(self) + } + #[must_use] + fn indent(&self, level: IndentLevel) -> Self { + Self::cast(level.increase_indent(self.syntax().clone())).unwrap() + } + #[must_use] + fn dedent(&self, level: IndentLevel) -> Self { + Self::cast(level.decrease_indent(self.syntax().clone())).unwrap() + } + #[must_use] + fn reset_indent(&self) -> Self { + let level = IndentLevel::from_node(self.syntax()); + self.dedent(level) + } +} + +impl<N: AstNode + Clone> AstNodeEdit for N {} + +fn single_node(element: impl Into<SyntaxElement>) -> RangeInclusive<SyntaxElement> { + let element = element.into(); + element.clone()..=element +} + +#[test] +fn test_increase_indent() { + let arm_list = { + let arm = make::match_arm(iter::once(make::wildcard_pat().into()), make::expr_unit()); + make::match_arm_list(vec![arm.clone(), arm]) + }; + assert_eq!( + arm_list.syntax().to_string(), + "{ + _ => (), + _ => (), +}" + ); + let indented = arm_list.indent(IndentLevel(2)); + assert_eq!( + indented.syntax().to_string(), + "{ + _ => (), + _ => (), + }" + ); +} diff --git a/crates/syntax/src/ast/expr_ext.rs b/crates/syntax/src/ast/expr_ext.rs new file mode 100644 index 00000000000..f5ba872233f --- /dev/null +++ b/crates/syntax/src/ast/expr_ext.rs @@ -0,0 +1,418 @@ +//! Various extension methods to ast Expr Nodes, which are hard to code-generate. + +use crate::{ + ast::{self, support, AstChildren, AstNode}, + SmolStr, + SyntaxKind::*, + SyntaxToken, T, +}; + +impl ast::AttrsOwner for ast::Expr {} + +impl ast::Expr { + pub fn is_block_like(&self) -> bool { + match self { + ast::Expr::IfExpr(_) + | ast::Expr::LoopExpr(_) + | ast::Expr::ForExpr(_) + | ast::Expr::WhileExpr(_) + | ast::Expr::BlockExpr(_) + | ast::Expr::MatchExpr(_) + | ast::Expr::EffectExpr(_) => true, + _ => false, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ElseBranch { + Block(ast::BlockExpr), + IfExpr(ast::IfExpr), +} + +impl ast::IfExpr { + pub fn then_branch(&self) -> Option<ast::BlockExpr> { + self.blocks().next() + } + pub fn else_branch(&self) -> Option<ElseBranch> { + let res = match self.blocks().nth(1) { + Some(block) => ElseBranch::Block(block), + None => { + let elif: ast::IfExpr = support::child(self.syntax())?; + ElseBranch::IfExpr(elif) + } + }; + Some(res) + } + + pub fn blocks(&self) -> AstChildren<ast::BlockExpr> { + support::children(self.syntax()) + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum PrefixOp { + /// The `*` operator for dereferencing + Deref, + /// The `!` operator for logical inversion + Not, + /// The `-` operator for negation + Neg, +} + +impl ast::PrefixExpr { + pub fn op_kind(&self) -> Option<PrefixOp> { + match self.op_token()?.kind() { + T![*] => Some(PrefixOp::Deref), + T![!] => Some(PrefixOp::Not), + T![-] => Some(PrefixOp::Neg), + _ => None, + } + } + + pub fn op_token(&self) -> Option<SyntaxToken> { + self.syntax().first_child_or_token()?.into_token() + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum BinOp { + /// The `||` operator for boolean OR + BooleanOr, + /// The `&&` operator for boolean AND + BooleanAnd, + /// The `==` operator for equality testing + EqualityTest, + /// The `!=` operator for equality testing + NegatedEqualityTest, + /// The `<=` operator for lesser-equal testing + LesserEqualTest, + /// The `>=` operator for greater-equal testing + GreaterEqualTest, + /// The `<` operator for comparison + LesserTest, + /// The `>` operator for comparison + GreaterTest, + /// The `+` operator for addition + Addition, + /// The `*` operator for multiplication + Multiplication, + /// The `-` operator for subtraction + Subtraction, + /// The `/` operator for division + Division, + /// The `%` operator for remainder after division + Remainder, + /// The `<<` operator for left shift + LeftShift, + /// The `>>` operator for right shift + RightShift, + /// The `^` operator for bitwise XOR + BitwiseXor, + /// The `|` operator for bitwise OR + BitwiseOr, + /// The `&` operator for bitwise AND + BitwiseAnd, + /// The `=` operator for assignment + Assignment, + /// The `+=` operator for assignment after addition + AddAssign, + /// The `/=` operator for assignment after division + DivAssign, + /// The `*=` operator for assignment after multiplication + MulAssign, + /// The `%=` operator for assignment after remainders + RemAssign, + /// The `>>=` operator for assignment after shifting right + ShrAssign, + /// The `<<=` operator for assignment after shifting left + ShlAssign, + /// The `-=` operator for assignment after subtraction + SubAssign, + /// The `|=` operator for assignment after bitwise OR + BitOrAssign, + /// The `&=` operator for assignment after bitwise AND + BitAndAssign, + /// The `^=` operator for assignment after bitwise XOR + BitXorAssign, +} + +impl BinOp { + pub fn is_assignment(self) -> bool { + match self { + BinOp::Assignment + | BinOp::AddAssign + | BinOp::DivAssign + | BinOp::MulAssign + | BinOp::RemAssign + | BinOp::ShrAssign + | BinOp::ShlAssign + | BinOp::SubAssign + | BinOp::BitOrAssign + | BinOp::BitAndAssign + | BinOp::BitXorAssign => true, + _ => false, + } + } +} + +impl ast::BinExpr { + pub fn op_details(&self) -> Option<(SyntaxToken, BinOp)> { + self.syntax().children_with_tokens().filter_map(|it| it.into_token()).find_map(|c| { + let bin_op = match c.kind() { + T![||] => BinOp::BooleanOr, + T![&&] => BinOp::BooleanAnd, + T![==] => BinOp::EqualityTest, + T![!=] => BinOp::NegatedEqualityTest, + T![<=] => BinOp::LesserEqualTest, + T![>=] => BinOp::GreaterEqualTest, + T![<] => BinOp::LesserTest, + T![>] => BinOp::GreaterTest, + T![+] => BinOp::Addition, + T![*] => BinOp::Multiplication, + T![-] => BinOp::Subtraction, + T![/] => BinOp::Division, + T![%] => BinOp::Remainder, + T![<<] => BinOp::LeftShift, + T![>>] => BinOp::RightShift, + T![^] => BinOp::BitwiseXor, + T![|] => BinOp::BitwiseOr, + T![&] => BinOp::BitwiseAnd, + T![=] => BinOp::Assignment, + T![+=] => BinOp::AddAssign, + T![/=] => BinOp::DivAssign, + T![*=] => BinOp::MulAssign, + T![%=] => BinOp::RemAssign, + T![>>=] => BinOp::ShrAssign, + T![<<=] => BinOp::ShlAssign, + T![-=] => BinOp::SubAssign, + T![|=] => BinOp::BitOrAssign, + T![&=] => BinOp::BitAndAssign, + T![^=] => BinOp::BitXorAssign, + _ => return None, + }; + Some((c, bin_op)) + }) + } + + pub fn op_kind(&self) -> Option<BinOp> { + self.op_details().map(|t| t.1) + } + + pub fn op_token(&self) -> Option<SyntaxToken> { + self.op_details().map(|t| t.0) + } + + pub fn lhs(&self) -> Option<ast::Expr> { + support::children(self.syntax()).next() + } + + pub fn rhs(&self) -> Option<ast::Expr> { + support::children(self.syntax()).nth(1) + } + + pub fn sub_exprs(&self) -> (Option<ast::Expr>, Option<ast::Expr>) { + let mut children = support::children(self.syntax()); + let first = children.next(); + let second = children.next(); + (first, second) + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum RangeOp { + /// `..` + Exclusive, + /// `..=` + Inclusive, +} + +impl ast::RangeExpr { + fn op_details(&self) -> Option<(usize, SyntaxToken, RangeOp)> { + self.syntax().children_with_tokens().enumerate().find_map(|(ix, child)| { + let token = child.into_token()?; + let bin_op = match token.kind() { + T![..] => RangeOp::Exclusive, + T![..=] => RangeOp::Inclusive, + _ => return None, + }; + Some((ix, token, bin_op)) + }) + } + + pub fn op_kind(&self) -> Option<RangeOp> { + self.op_details().map(|t| t.2) + } + + pub fn op_token(&self) -> Option<SyntaxToken> { + self.op_details().map(|t| t.1) + } + + pub fn start(&self) -> Option<ast::Expr> { + let op_ix = self.op_details()?.0; + self.syntax() + .children_with_tokens() + .take(op_ix) + .find_map(|it| ast::Expr::cast(it.into_node()?)) + } + + pub fn end(&self) -> Option<ast::Expr> { + let op_ix = self.op_details()?.0; + self.syntax() + .children_with_tokens() + .skip(op_ix + 1) + .find_map(|it| ast::Expr::cast(it.into_node()?)) + } +} + +impl ast::IndexExpr { + pub fn base(&self) -> Option<ast::Expr> { + support::children(self.syntax()).next() + } + pub fn index(&self) -> Option<ast::Expr> { + support::children(self.syntax()).nth(1) + } +} + +pub enum ArrayExprKind { + Repeat { initializer: Option<ast::Expr>, repeat: Option<ast::Expr> }, + ElementList(AstChildren<ast::Expr>), +} + +impl ast::ArrayExpr { + pub fn kind(&self) -> ArrayExprKind { + if self.is_repeat() { + ArrayExprKind::Repeat { + initializer: support::children(self.syntax()).next(), + repeat: support::children(self.syntax()).nth(1), + } + } else { + ArrayExprKind::ElementList(support::children(self.syntax())) + } + } + + fn is_repeat(&self) -> bool { + self.syntax().children_with_tokens().any(|it| it.kind() == T![;]) + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum LiteralKind { + String, + ByteString, + Char, + Byte, + IntNumber { suffix: Option<SmolStr> }, + FloatNumber { suffix: Option<SmolStr> }, + Bool(bool), +} + +impl ast::Literal { + pub fn token(&self) -> SyntaxToken { + self.syntax() + .children_with_tokens() + .find(|e| e.kind() != ATTR && !e.kind().is_trivia()) + .and_then(|e| e.into_token()) + .unwrap() + } + + fn find_suffix(text: &str, possible_suffixes: &[&str]) -> Option<SmolStr> { + possible_suffixes + .iter() + .find(|&suffix| text.ends_with(suffix)) + .map(|&suffix| SmolStr::new(suffix)) + } + + pub fn kind(&self) -> LiteralKind { + const INT_SUFFIXES: [&str; 12] = [ + "u64", "u32", "u16", "u8", "usize", "isize", "i64", "i32", "i16", "i8", "u128", "i128", + ]; + const FLOAT_SUFFIXES: [&str; 2] = ["f32", "f64"]; + + let token = self.token(); + + match token.kind() { + INT_NUMBER => { + // FYI: there was a bug here previously, thus the if statement below is necessary. + // The lexer treats e.g. `1f64` as an integer literal. See + // https://github.com/rust-analyzer/rust-analyzer/issues/1592 + // and the comments on the linked PR. + + let text = token.text(); + if let suffix @ Some(_) = Self::find_suffix(&text, &FLOAT_SUFFIXES) { + LiteralKind::FloatNumber { suffix } + } else { + LiteralKind::IntNumber { suffix: Self::find_suffix(&text, &INT_SUFFIXES) } + } + } + FLOAT_NUMBER => { + let text = token.text(); + LiteralKind::FloatNumber { suffix: Self::find_suffix(&text, &FLOAT_SUFFIXES) } + } + STRING | RAW_STRING => LiteralKind::String, + T![true] => LiteralKind::Bool(true), + T![false] => LiteralKind::Bool(false), + BYTE_STRING | RAW_BYTE_STRING => LiteralKind::ByteString, + CHAR => LiteralKind::Char, + BYTE => LiteralKind::Byte, + _ => unreachable!(), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Effect { + Async(SyntaxToken), + Unsafe(SyntaxToken), + Try(SyntaxToken), + // Very much not an effect, but we stuff it into this node anyway + Label(ast::Label), +} + +impl ast::EffectExpr { + pub fn effect(&self) -> Effect { + if let Some(token) = self.async_token() { + return Effect::Async(token); + } + if let Some(token) = self.unsafe_token() { + return Effect::Unsafe(token); + } + if let Some(token) = self.try_token() { + return Effect::Try(token); + } + if let Some(label) = self.label() { + return Effect::Label(label); + } + unreachable!("ast::EffectExpr without Effect") + } +} + +impl ast::BlockExpr { + /// false if the block is an intrinsic part of the syntax and can't be + /// replaced with arbitrary expression. + /// + /// ```not_rust + /// fn foo() { not_stand_alone } + /// const FOO: () = { stand_alone }; + /// ``` + pub fn is_standalone(&self) -> bool { + let parent = match self.syntax().parent() { + Some(it) => it, + None => return true, + }; + !matches!(parent.kind(), FN | IF_EXPR | WHILE_EXPR | LOOP_EXPR | EFFECT_EXPR) + } +} + +#[test] +fn test_literal_with_attr() { + let parse = ast::SourceFile::parse(r#"const _: &str = { #[attr] "Hello" };"#); + let lit = parse.tree().syntax().descendants().find_map(ast::Literal::cast).unwrap(); + assert_eq!(lit.token().text(), r#""Hello""#); +} + +impl ast::RecordExprField { + pub fn parent_record_lit(&self) -> ast::RecordExpr { + self.syntax().ancestors().find_map(ast::RecordExpr::cast).unwrap() + } +} diff --git a/crates/syntax/src/ast/generated.rs b/crates/syntax/src/ast/generated.rs new file mode 100644 index 00000000000..4a6f41ee71f --- /dev/null +++ b/crates/syntax/src/ast/generated.rs @@ -0,0 +1,41 @@ +//! This file is actually hand-written, but the submodules are indeed generated. +#[rustfmt::skip] +mod nodes; +#[rustfmt::skip] +mod tokens; + +use crate::{ + AstNode, + SyntaxKind::{self, *}, + SyntaxNode, +}; + +pub use {nodes::*, tokens::*}; + +// Stmt is the only nested enum, so it's easier to just hand-write it +impl AstNode for Stmt { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + LET_STMT | EXPR_STMT => true, + _ => Item::can_cast(kind), + } + } + fn cast(syntax: SyntaxNode) -> Option<Self> { + let res = match syntax.kind() { + LET_STMT => Stmt::LetStmt(LetStmt { syntax }), + EXPR_STMT => Stmt::ExprStmt(ExprStmt { syntax }), + _ => { + let item = Item::cast(syntax)?; + Stmt::Item(item) + } + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + Stmt::LetStmt(it) => &it.syntax, + Stmt::ExprStmt(it) => &it.syntax, + Stmt::Item(it) => it.syntax(), + } + } +} diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs new file mode 100644 index 00000000000..3d49309d148 --- /dev/null +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -0,0 +1,4067 @@ +//! Generated file, do not edit by hand, see `xtask/src/codegen` + +use crate::{ + ast::{self, support, AstChildren, AstNode}, + SyntaxKind::{self, *}, + SyntaxNode, SyntaxToken, T, +}; +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Name { + pub(crate) syntax: SyntaxNode, +} +impl Name { + pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct NameRef { + pub(crate) syntax: SyntaxNode, +} +impl NameRef { + pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Path { + pub(crate) syntax: SyntaxNode, +} +impl Path { + pub fn qualifier(&self) -> Option<Path> { support::child(&self.syntax) } + pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } + pub fn segment(&self) -> Option<PathSegment> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct PathSegment { + pub(crate) syntax: SyntaxNode, +} +impl PathSegment { + pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) } + pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) } + pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) } + pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } + pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } + pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) } + pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) } + pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } + pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } + pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) } + pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) } + pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct GenericArgList { + pub(crate) syntax: SyntaxNode, +} +impl GenericArgList { + pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } + pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } + pub fn generic_args(&self) -> AstChildren<GenericArg> { support::children(&self.syntax) } + pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ParamList { + pub(crate) syntax: SyntaxNode, +} +impl ParamList { + pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } + pub fn self_param(&self) -> Option<SelfParam> { support::child(&self.syntax) } + pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) } + pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) } + pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RetType { + pub(crate) syntax: SyntaxNode, +} +impl RetType { + pub fn thin_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![->]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct PathType { + pub(crate) syntax: SyntaxNode, +} +impl PathType { + pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TypeArg { + pub(crate) syntax: SyntaxNode, +} +impl TypeArg { + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AssocTypeArg { + pub(crate) syntax: SyntaxNode, +} +impl ast::TypeBoundsOwner for AssocTypeArg {} +impl AssocTypeArg { + pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } + pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct LifetimeArg { + pub(crate) syntax: SyntaxNode, +} +impl LifetimeArg { + pub fn lifetime_token(&self) -> Option<SyntaxToken> { + support::token(&self.syntax, T![lifetime]) + } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ConstArg { + pub(crate) syntax: SyntaxNode, +} +impl ConstArg { + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TypeBoundList { + pub(crate) syntax: SyntaxNode, +} +impl TypeBoundList { + pub fn bounds(&self) -> AstChildren<TypeBound> { support::children(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct MacroCall { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for MacroCall {} +impl ast::NameOwner for MacroCall {} +impl MacroCall { + pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } + pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } + pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) } + pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Attr { + pub(crate) syntax: SyntaxNode, +} +impl Attr { + pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) } + pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } + pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } + pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } + pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } + pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) } + pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) } + pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TokenTree { + pub(crate) syntax: SyntaxNode, +} +impl TokenTree { + pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } + pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } + pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } + pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } + pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } + pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct MacroItems { + pub(crate) syntax: SyntaxNode, +} +impl ast::ModuleItemOwner for MacroItems {} +impl MacroItems {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct MacroStmts { + pub(crate) syntax: SyntaxNode, +} +impl MacroStmts { + pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct SourceFile { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for SourceFile {} +impl ast::ModuleItemOwner for SourceFile {} +impl SourceFile { + pub fn shebang_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![shebang]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Const { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for Const {} +impl ast::NameOwner for Const {} +impl ast::VisibilityOwner for Const {} +impl Const { + pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) } + pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } + pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) } + pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } + pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } + pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Enum { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for Enum {} +impl ast::NameOwner for Enum {} +impl ast::VisibilityOwner for Enum {} +impl ast::GenericParamsOwner for Enum {} +impl Enum { + pub fn enum_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![enum]) } + pub fn variant_list(&self) -> Option<VariantList> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ExternBlock { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for ExternBlock {} +impl ExternBlock { + pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) } + pub fn extern_item_list(&self) -> Option<ExternItemList> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ExternCrate { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for ExternCrate {} +impl ast::VisibilityOwner for ExternCrate {} +impl ExternCrate { + pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) } + pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) } + pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } + pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) } + pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) } + pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Fn { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for Fn {} +impl ast::NameOwner for Fn {} +impl ast::VisibilityOwner for Fn {} +impl ast::GenericParamsOwner for Fn {} +impl Fn { + pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) } + pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } + pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } + pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } + pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) } + pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) } + pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) } + pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } + pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) } + pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Impl { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for Impl {} +impl ast::VisibilityOwner for Impl {} +impl ast::GenericParamsOwner for Impl {} +impl Impl { + pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) } + pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } + pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) } + pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } + pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } + pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) } + pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Module { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for Module {} +impl ast::NameOwner for Module {} +impl ast::VisibilityOwner for Module {} +impl Module { + pub fn mod_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mod]) } + pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) } + pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Static { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for Static {} +impl ast::NameOwner for Static {} +impl ast::VisibilityOwner for Static {} +impl Static { + pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) } + pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } + pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } + pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } + pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Struct { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for Struct {} +impl ast::NameOwner for Struct {} +impl ast::VisibilityOwner for Struct {} +impl ast::GenericParamsOwner for Struct {} +impl Struct { + pub fn struct_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![struct]) } + pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } + pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Trait { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for Trait {} +impl ast::NameOwner for Trait {} +impl ast::VisibilityOwner for Trait {} +impl ast::GenericParamsOwner for Trait {} +impl ast::TypeBoundsOwner for Trait {} +impl Trait { + pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } + pub fn auto_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![auto]) } + pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) } + pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TypeAlias { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for TypeAlias {} +impl ast::NameOwner for TypeAlias {} +impl ast::VisibilityOwner for TypeAlias {} +impl ast::GenericParamsOwner for TypeAlias {} +impl ast::TypeBoundsOwner for TypeAlias {} +impl TypeAlias { + pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) } + pub fn type_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![type]) } + pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } + pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Union { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for Union {} +impl ast::NameOwner for Union {} +impl ast::VisibilityOwner for Union {} +impl ast::GenericParamsOwner for Union {} +impl Union { + pub fn union_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![union]) } + pub fn record_field_list(&self) -> Option<RecordFieldList> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Use { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for Use {} +impl ast::VisibilityOwner for Use {} +impl Use { + pub fn use_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![use]) } + pub fn use_tree(&self) -> Option<UseTree> { support::child(&self.syntax) } + pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Visibility { + pub(crate) syntax: SyntaxNode, +} +impl Visibility { + pub fn pub_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![pub]) } + pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } + pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) } + pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) } + pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) } + pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) } + pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } + pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ItemList { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for ItemList {} +impl ast::ModuleItemOwner for ItemList {} +impl ItemList { + pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } + pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Rename { + pub(crate) syntax: SyntaxNode, +} +impl ast::NameOwner for Rename {} +impl Rename { + pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) } + pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct UseTree { + pub(crate) syntax: SyntaxNode, +} +impl UseTree { + pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } + pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } + pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) } + pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) } + pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct UseTreeList { + pub(crate) syntax: SyntaxNode, +} +impl UseTreeList { + pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } + pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) } + pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Abi { + pub(crate) syntax: SyntaxNode, +} +impl Abi { + pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct GenericParamList { + pub(crate) syntax: SyntaxNode, +} +impl GenericParamList { + pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } + pub fn generic_params(&self) -> AstChildren<GenericParam> { support::children(&self.syntax) } + pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct WhereClause { + pub(crate) syntax: SyntaxNode, +} +impl WhereClause { + pub fn where_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![where]) } + pub fn predicates(&self) -> AstChildren<WherePred> { support::children(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct BlockExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for BlockExpr {} +impl BlockExpr { + pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } + pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct SelfParam { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for SelfParam {} +impl SelfParam { + pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } + pub fn lifetime_token(&self) -> Option<SyntaxToken> { + support::token(&self.syntax, T![lifetime]) + } + pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } + pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) } + pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Param { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for Param {} +impl Param { + pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } + pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } + pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RecordFieldList { + pub(crate) syntax: SyntaxNode, +} +impl RecordFieldList { + pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } + pub fn fields(&self) -> AstChildren<RecordField> { support::children(&self.syntax) } + pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TupleFieldList { + pub(crate) syntax: SyntaxNode, +} +impl TupleFieldList { + pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } + pub fn fields(&self) -> AstChildren<TupleField> { support::children(&self.syntax) } + pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RecordField { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for RecordField {} +impl ast::NameOwner for RecordField {} +impl ast::VisibilityOwner for RecordField {} +impl RecordField { + pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TupleField { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for TupleField {} +impl ast::VisibilityOwner for TupleField {} +impl TupleField { + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct VariantList { + pub(crate) syntax: SyntaxNode, +} +impl VariantList { + pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } + pub fn variants(&self) -> AstChildren<Variant> { support::children(&self.syntax) } + pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Variant { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for Variant {} +impl ast::NameOwner for Variant {} +impl ast::VisibilityOwner for Variant {} +impl Variant { + pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) } + pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AssocItemList { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for AssocItemList {} +impl AssocItemList { + pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } + pub fn assoc_items(&self) -> AstChildren<AssocItem> { support::children(&self.syntax) } + pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ExternItemList { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for ExternItemList {} +impl ExternItemList { + pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } + pub fn extern_items(&self) -> AstChildren<ExternItem> { support::children(&self.syntax) } + pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ConstParam { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for ConstParam {} +impl ast::NameOwner for ConstParam {} +impl ConstParam { + pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } + pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } + pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } + pub fn default_val(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct LifetimeParam { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for LifetimeParam {} +impl ast::TypeBoundsOwner for LifetimeParam {} +impl LifetimeParam { + pub fn lifetime_token(&self) -> Option<SyntaxToken> { + support::token(&self.syntax, T![lifetime]) + } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TypeParam { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for TypeParam {} +impl ast::NameOwner for TypeParam {} +impl ast::TypeBoundsOwner for TypeParam {} +impl TypeParam { + pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } + pub fn default_type(&self) -> Option<Type> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct WherePred { + pub(crate) syntax: SyntaxNode, +} +impl ast::TypeBoundsOwner for WherePred {} +impl WherePred { + pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) } + pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) } + pub fn lifetime_token(&self) -> Option<SyntaxToken> { + support::token(&self.syntax, T![lifetime]) + } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Literal { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for Literal {} +impl Literal {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ExprStmt { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for ExprStmt {} +impl ExprStmt { + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct LetStmt { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for LetStmt {} +impl LetStmt { + pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) } + pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } + pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } + pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } + pub fn initializer(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } +} +#[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<SyntaxToken> { support::token(&self.syntax, T!['[']) } + pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } + pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AwaitExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for AwaitExpr {} +impl AwaitExpr { + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) } + pub fn await_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![await]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct BinExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for BinExpr {} +impl BinExpr {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct BoxExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for BoxExpr {} +impl BoxExpr { + pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct BreakExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for BreakExpr {} +impl BreakExpr { + pub fn break_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![break]) } + pub fn lifetime_token(&self) -> Option<SyntaxToken> { + support::token(&self.syntax, T![lifetime]) + } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct CallExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for CallExpr {} +impl ast::ArgListOwner for CallExpr {} +impl CallExpr { + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct CastExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for CastExpr {} +impl CastExpr { + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ClosureExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for ClosureExpr {} +impl ClosureExpr { + pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) } + pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } + pub fn move_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![move]) } + pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) } + pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } + pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ContinueExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for ContinueExpr {} +impl ContinueExpr { + pub fn continue_token(&self) -> Option<SyntaxToken> { + support::token(&self.syntax, T![continue]) + } + pub fn lifetime_token(&self) -> Option<SyntaxToken> { + support::token(&self.syntax, T![lifetime]) + } +} +#[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<Label> { support::child(&self.syntax) } + pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) } + pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } + pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } + pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct FieldExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for FieldExpr {} +impl FieldExpr { + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) } + pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ForExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for ForExpr {} +impl ast::LoopBodyOwner for ForExpr {} +impl ForExpr { + pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) } + pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } + pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) } + pub fn iterable(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[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<SyntaxToken> { support::token(&self.syntax, T![if]) } + pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) } + pub fn else_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![else]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct IndexExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for IndexExpr {} +impl IndexExpr { + pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } + pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } +} +#[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<SyntaxToken> { support::token(&self.syntax, T![loop]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct MatchExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for MatchExpr {} +impl MatchExpr { + pub fn match_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![match]) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn match_arm_list(&self) -> Option<MatchArmList> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct MethodCallExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for MethodCallExpr {} +impl ast::ArgListOwner for MethodCallExpr {} +impl MethodCallExpr { + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) } + pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } + pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) } +} +#[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<SyntaxToken> { support::token(&self.syntax, T!['(']) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct PathExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for PathExpr {} +impl PathExpr { + pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct PrefixExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for PrefixExpr {} +impl PrefixExpr { + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RangeExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for RangeExpr {} +impl RangeExpr {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RecordExpr { + pub(crate) syntax: SyntaxNode, +} +impl RecordExpr { + pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } + pub fn record_expr_field_list(&self) -> Option<RecordExprFieldList> { + support::child(&self.syntax) + } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RefExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for RefExpr {} +impl RefExpr { + pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } + pub fn raw_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![raw]) } + pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } + pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ReturnExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for ReturnExpr {} +impl ReturnExpr { + pub fn return_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![return]) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TryExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for TryExpr {} +impl TryExpr { + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) } +} +#[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<SyntaxToken> { support::token(&self.syntax, T!['(']) } + pub fn fields(&self) -> AstChildren<Expr> { support::children(&self.syntax) } + pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct WhileExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for WhileExpr {} +impl ast::LoopBodyOwner for WhileExpr {} +impl WhileExpr { + pub fn while_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![while]) } + pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Label { + pub(crate) syntax: SyntaxNode, +} +impl Label { + pub fn lifetime_token(&self) -> Option<SyntaxToken> { + support::token(&self.syntax, T![lifetime]) + } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RecordExprFieldList { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for RecordExprFieldList {} +impl RecordExprFieldList { + pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } + pub fn fields(&self) -> AstChildren<RecordExprField> { support::children(&self.syntax) } + pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) } + pub fn spread(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RecordExprField { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for RecordExprField {} +impl RecordExprField { + pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } + pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ArgList { + pub(crate) syntax: SyntaxNode, +} +impl ArgList { + pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } + pub fn args(&self) -> AstChildren<Expr> { support::children(&self.syntax) } + pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Condition { + pub(crate) syntax: SyntaxNode, +} +impl Condition { + pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) } + pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } + pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct MatchArmList { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for MatchArmList {} +impl MatchArmList { + pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } + pub fn arms(&self) -> AstChildren<MatchArm> { support::children(&self.syntax) } + pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct MatchArm { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for MatchArm {} +impl MatchArm { + pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } + pub fn guard(&self) -> Option<MatchGuard> { support::child(&self.syntax) } + pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct MatchGuard { + pub(crate) syntax: SyntaxNode, +} +impl MatchGuard { + pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ArrayType { + pub(crate) syntax: SyntaxNode, +} +impl ArrayType { + pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } + pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } + pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } + pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct DynTraitType { + pub(crate) syntax: SyntaxNode, +} +impl DynTraitType { + pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) } + pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct FnPtrType { + pub(crate) syntax: SyntaxNode, +} +impl FnPtrType { + pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } + pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } + pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } + pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) } + pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) } + pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) } + pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ForType { + pub(crate) syntax: SyntaxNode, +} +impl ForType { + pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) } + pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ImplTraitType { + pub(crate) syntax: SyntaxNode, +} +impl ImplTraitType { + pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) } + pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct InferType { + pub(crate) syntax: SyntaxNode, +} +impl InferType { + pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct NeverType { + pub(crate) syntax: SyntaxNode, +} +impl NeverType { + pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ParenType { + pub(crate) syntax: SyntaxNode, +} +impl ParenType { + pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } + pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct PtrType { + pub(crate) syntax: SyntaxNode, +} +impl PtrType { + pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) } + pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } + pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RefType { + pub(crate) syntax: SyntaxNode, +} +impl RefType { + pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } + pub fn lifetime_token(&self) -> Option<SyntaxToken> { + support::token(&self.syntax, T![lifetime]) + } + pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct SliceType { + pub(crate) syntax: SyntaxNode, +} +impl SliceType { + pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } + pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TupleType { + pub(crate) syntax: SyntaxNode, +} +impl TupleType { + pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } + pub fn fields(&self) -> AstChildren<Type> { support::children(&self.syntax) } + pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TypeBound { + pub(crate) syntax: SyntaxNode, +} +impl TypeBound { + pub fn lifetime_token(&self) -> Option<SyntaxToken> { + support::token(&self.syntax, T![lifetime]) + } + pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) } + pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct IdentPat { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for IdentPat {} +impl ast::NameOwner for IdentPat {} +impl IdentPat { + pub fn ref_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ref]) } + pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } + pub fn at_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![@]) } + pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct BoxPat { + pub(crate) syntax: SyntaxNode, +} +impl BoxPat { + pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) } + pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RestPat { + pub(crate) syntax: SyntaxNode, +} +impl RestPat { + pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct LiteralPat { + pub(crate) syntax: SyntaxNode, +} +impl LiteralPat { + pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct MacroPat { + pub(crate) syntax: SyntaxNode, +} +impl MacroPat { + pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct OrPat { + pub(crate) syntax: SyntaxNode, +} +impl OrPat { + pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ParenPat { + pub(crate) syntax: SyntaxNode, +} +impl ParenPat { + pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } + pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } + pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct PathPat { + pub(crate) syntax: SyntaxNode, +} +impl PathPat { + pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct WildcardPat { + pub(crate) syntax: SyntaxNode, +} +impl WildcardPat { + pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RangePat { + pub(crate) syntax: SyntaxNode, +} +impl RangePat {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RecordPat { + pub(crate) syntax: SyntaxNode, +} +impl RecordPat { + pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } + pub fn record_pat_field_list(&self) -> Option<RecordPatFieldList> { + support::child(&self.syntax) + } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RefPat { + pub(crate) syntax: SyntaxNode, +} +impl RefPat { + pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } + pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } + pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct SlicePat { + pub(crate) syntax: SyntaxNode, +} +impl SlicePat { + pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } + pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) } + pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TuplePat { + pub(crate) syntax: SyntaxNode, +} +impl TuplePat { + pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } + pub fn fields(&self) -> AstChildren<Pat> { support::children(&self.syntax) } + pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TupleStructPat { + pub(crate) syntax: SyntaxNode, +} +impl TupleStructPat { + pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } + pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } + pub fn fields(&self) -> AstChildren<Pat> { support::children(&self.syntax) } + pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RecordPatFieldList { + pub(crate) syntax: SyntaxNode, +} +impl RecordPatFieldList { + pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } + pub fn fields(&self) -> AstChildren<RecordPatField> { support::children(&self.syntax) } + pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) } + pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RecordPatField { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for RecordPatField {} +impl RecordPatField { + pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } + pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } + pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum GenericArg { + TypeArg(TypeArg), + AssocTypeArg(AssocTypeArg), + LifetimeArg(LifetimeArg), + ConstArg(ConstArg), +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum Type { + ArrayType(ArrayType), + DynTraitType(DynTraitType), + FnPtrType(FnPtrType), + ForType(ForType), + ImplTraitType(ImplTraitType), + InferType(InferType), + NeverType(NeverType), + ParenType(ParenType), + PathType(PathType), + PtrType(PtrType), + RefType(RefType), + SliceType(SliceType), + TupleType(TupleType), +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum Expr { + ArrayExpr(ArrayExpr), + AwaitExpr(AwaitExpr), + BinExpr(BinExpr), + BlockExpr(BlockExpr), + BoxExpr(BoxExpr), + BreakExpr(BreakExpr), + CallExpr(CallExpr), + CastExpr(CastExpr), + ClosureExpr(ClosureExpr), + ContinueExpr(ContinueExpr), + EffectExpr(EffectExpr), + FieldExpr(FieldExpr), + ForExpr(ForExpr), + IfExpr(IfExpr), + IndexExpr(IndexExpr), + Literal(Literal), + LoopExpr(LoopExpr), + MacroCall(MacroCall), + MatchExpr(MatchExpr), + MethodCallExpr(MethodCallExpr), + ParenExpr(ParenExpr), + PathExpr(PathExpr), + PrefixExpr(PrefixExpr), + RangeExpr(RangeExpr), + RecordExpr(RecordExpr), + RefExpr(RefExpr), + ReturnExpr(ReturnExpr), + TryExpr(TryExpr), + TupleExpr(TupleExpr), + WhileExpr(WhileExpr), +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum Item { + Const(Const), + Enum(Enum), + ExternBlock(ExternBlock), + ExternCrate(ExternCrate), + Fn(Fn), + Impl(Impl), + MacroCall(MacroCall), + Module(Module), + Static(Static), + Struct(Struct), + Trait(Trait), + TypeAlias(TypeAlias), + Union(Union), + Use(Use), +} +impl ast::AttrsOwner for Item {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum Stmt { + ExprStmt(ExprStmt), + Item(Item), + LetStmt(LetStmt), +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum Pat { + IdentPat(IdentPat), + BoxPat(BoxPat), + RestPat(RestPat), + LiteralPat(LiteralPat), + MacroPat(MacroPat), + OrPat(OrPat), + ParenPat(ParenPat), + PathPat(PathPat), + WildcardPat(WildcardPat), + RangePat(RangePat), + RecordPat(RecordPat), + RefPat(RefPat), + SlicePat(SlicePat), + TuplePat(TuplePat), + TupleStructPat(TupleStructPat), +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum FieldList { + RecordFieldList(RecordFieldList), + TupleFieldList(TupleFieldList), +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum AdtDef { + Enum(Enum), + Struct(Struct), + Union(Union), +} +impl ast::AttrsOwner for AdtDef {} +impl ast::GenericParamsOwner for AdtDef {} +impl ast::NameOwner for AdtDef {} +impl ast::VisibilityOwner for AdtDef {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum AssocItem { + Const(Const), + Fn(Fn), + MacroCall(MacroCall), + TypeAlias(TypeAlias), +} +impl ast::AttrsOwner for AssocItem {} +impl ast::NameOwner for AssocItem {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ExternItem { + Fn(Fn), + MacroCall(MacroCall), + Static(Static), +} +impl ast::AttrsOwner for ExternItem {} +impl ast::NameOwner for ExternItem {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum GenericParam { + ConstParam(ConstParam), + LifetimeParam(LifetimeParam), + TypeParam(TypeParam), +} +impl ast::AttrsOwner for GenericParam {} +impl AstNode for Name { + fn can_cast(kind: SyntaxKind) -> bool { kind == NAME } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for NameRef { + fn can_cast(kind: SyntaxKind) -> bool { kind == NAME_REF } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Path { + fn can_cast(kind: SyntaxKind) -> bool { kind == PATH } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for PathSegment { + fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_SEGMENT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for GenericArgList { + fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_ARG_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ParamList { + fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RetType { + fn can_cast(kind: SyntaxKind) -> bool { kind == RET_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for PathType { + fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for TypeArg { + fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ARG } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for AssocTypeArg { + fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_TYPE_ARG } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for LifetimeArg { + fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_ARG } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ConstArg { + fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_ARG } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for TypeBoundList { + fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for MacroCall { + fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_CALL } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Attr { + fn can_cast(kind: SyntaxKind) -> bool { kind == ATTR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for TokenTree { + fn can_cast(kind: SyntaxKind) -> bool { kind == TOKEN_TREE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for MacroItems { + fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_ITEMS } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for MacroStmts { + fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_STMTS } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for SourceFile { + fn can_cast(kind: SyntaxKind) -> bool { kind == SOURCE_FILE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Const { + fn can_cast(kind: SyntaxKind) -> bool { kind == CONST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Enum { + fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ExternBlock { + fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_BLOCK } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ExternCrate { + fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_CRATE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Fn { + fn can_cast(kind: SyntaxKind) -> bool { kind == FN } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Impl { + fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Module { + fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Static { + fn can_cast(kind: SyntaxKind) -> bool { kind == STATIC } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Struct { + fn can_cast(kind: SyntaxKind) -> bool { kind == STRUCT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Trait { + fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for TypeAlias { + fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ALIAS } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Union { + fn can_cast(kind: SyntaxKind) -> bool { kind == UNION } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Use { + fn can_cast(kind: SyntaxKind) -> bool { kind == USE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Visibility { + fn can_cast(kind: SyntaxKind) -> bool { kind == VISIBILITY } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ItemList { + fn can_cast(kind: SyntaxKind) -> bool { kind == ITEM_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Rename { + fn can_cast(kind: SyntaxKind) -> bool { kind == RENAME } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for UseTree { + fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for UseTreeList { + fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Abi { + fn can_cast(kind: SyntaxKind) -> bool { kind == ABI } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for GenericParamList { + fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_PARAM_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for WhereClause { + fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_CLAUSE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for BlockExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for SelfParam { + fn can_cast(kind: SyntaxKind) -> bool { kind == SELF_PARAM } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Param { + fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RecordFieldList { + fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for TupleFieldList { + fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RecordField { + fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for TupleField { + fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for VariantList { + fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Variant { + fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for AssocItemList { + fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_ITEM_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ExternItemList { + fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_ITEM_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ConstParam { + fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_PARAM } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for LifetimeParam { + fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_PARAM } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for TypeParam { + fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_PARAM } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for WherePred { + fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_PRED } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Literal { + fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ExprStmt { + fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_STMT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for LetStmt { + fn can_cast(kind: SyntaxKind) -> bool { kind == LET_STMT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ArrayExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for AwaitExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == AWAIT_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for BinExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == BIN_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for BoxExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for BreakExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == BREAK_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for CallExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == CALL_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for CastExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == CAST_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ClosureExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == CLOSURE_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ContinueExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == CONTINUE_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for EffectExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == EFFECT_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for FieldExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == FIELD_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ForExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for IfExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == IF_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for IndexExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == INDEX_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for LoopExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == LOOP_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for MatchExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for MethodCallExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == METHOD_CALL_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ParenExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for PathExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for PrefixExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == PREFIX_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RangeExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RecordExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RefExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == REF_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ReturnExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == RETURN_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for TryExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for TupleExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for WhileExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == WHILE_EXPR } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Label { + fn can_cast(kind: SyntaxKind) -> bool { kind == LABEL } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RecordExprFieldList { + fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RecordExprField { + fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ArgList { + fn can_cast(kind: SyntaxKind) -> bool { kind == ARG_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Condition { + fn can_cast(kind: SyntaxKind) -> bool { kind == CONDITION } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for MatchArmList { + fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for MatchArm { + fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for MatchGuard { + fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_GUARD } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ArrayType { + fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for DynTraitType { + fn can_cast(kind: SyntaxKind) -> bool { kind == DYN_TRAIT_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for FnPtrType { + fn can_cast(kind: SyntaxKind) -> bool { kind == FN_PTR_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ForType { + fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ImplTraitType { + fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL_TRAIT_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for InferType { + fn can_cast(kind: SyntaxKind) -> bool { kind == INFER_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for NeverType { + fn can_cast(kind: SyntaxKind) -> bool { kind == NEVER_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ParenType { + fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for PtrType { + fn can_cast(kind: SyntaxKind) -> bool { kind == PTR_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RefType { + fn can_cast(kind: SyntaxKind) -> bool { kind == REF_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for SliceType { + fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for TupleType { + fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_TYPE } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for TypeBound { + fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for IdentPat { + fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for BoxPat { + fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RestPat { + fn can_cast(kind: SyntaxKind) -> bool { kind == REST_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for LiteralPat { + fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for MacroPat { + fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for OrPat { + fn can_cast(kind: SyntaxKind) -> bool { kind == OR_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for ParenPat { + fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for PathPat { + fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for WildcardPat { + fn can_cast(kind: SyntaxKind) -> bool { kind == WILDCARD_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RangePat { + fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RecordPat { + fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RefPat { + fn can_cast(kind: SyntaxKind) -> bool { kind == REF_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for SlicePat { + fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for TuplePat { + fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for TupleStructPat { + fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_STRUCT_PAT } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RecordPatFieldList { + fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD_LIST } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for RecordPatField { + fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD } + fn cast(syntax: SyntaxNode) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl From<TypeArg> for GenericArg { + fn from(node: TypeArg) -> GenericArg { GenericArg::TypeArg(node) } +} +impl From<AssocTypeArg> for GenericArg { + fn from(node: AssocTypeArg) -> GenericArg { GenericArg::AssocTypeArg(node) } +} +impl From<LifetimeArg> for GenericArg { + fn from(node: LifetimeArg) -> GenericArg { GenericArg::LifetimeArg(node) } +} +impl From<ConstArg> for GenericArg { + fn from(node: ConstArg) -> GenericArg { GenericArg::ConstArg(node) } +} +impl AstNode for GenericArg { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option<Self> { + let res = match syntax.kind() { + TYPE_ARG => GenericArg::TypeArg(TypeArg { syntax }), + ASSOC_TYPE_ARG => GenericArg::AssocTypeArg(AssocTypeArg { syntax }), + LIFETIME_ARG => GenericArg::LifetimeArg(LifetimeArg { syntax }), + CONST_ARG => GenericArg::ConstArg(ConstArg { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + GenericArg::TypeArg(it) => &it.syntax, + GenericArg::AssocTypeArg(it) => &it.syntax, + GenericArg::LifetimeArg(it) => &it.syntax, + GenericArg::ConstArg(it) => &it.syntax, + } + } +} +impl From<ArrayType> for Type { + fn from(node: ArrayType) -> Type { Type::ArrayType(node) } +} +impl From<DynTraitType> for Type { + fn from(node: DynTraitType) -> Type { Type::DynTraitType(node) } +} +impl From<FnPtrType> for Type { + fn from(node: FnPtrType) -> Type { Type::FnPtrType(node) } +} +impl From<ForType> for Type { + fn from(node: ForType) -> Type { Type::ForType(node) } +} +impl From<ImplTraitType> for Type { + fn from(node: ImplTraitType) -> Type { Type::ImplTraitType(node) } +} +impl From<InferType> for Type { + fn from(node: InferType) -> Type { Type::InferType(node) } +} +impl From<NeverType> for Type { + fn from(node: NeverType) -> Type { Type::NeverType(node) } +} +impl From<ParenType> for Type { + fn from(node: ParenType) -> Type { Type::ParenType(node) } +} +impl From<PathType> for Type { + fn from(node: PathType) -> Type { Type::PathType(node) } +} +impl From<PtrType> for Type { + fn from(node: PtrType) -> Type { Type::PtrType(node) } +} +impl From<RefType> for Type { + fn from(node: RefType) -> Type { Type::RefType(node) } +} +impl From<SliceType> for Type { + fn from(node: SliceType) -> Type { Type::SliceType(node) } +} +impl From<TupleType> for Type { + fn from(node: TupleType) -> Type { Type::TupleType(node) } +} +impl AstNode for Type { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + ARRAY_TYPE | DYN_TRAIT_TYPE | FN_PTR_TYPE | FOR_TYPE | IMPL_TRAIT_TYPE | INFER_TYPE + | NEVER_TYPE | PAREN_TYPE | PATH_TYPE | PTR_TYPE | REF_TYPE | SLICE_TYPE + | TUPLE_TYPE => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option<Self> { + let res = match syntax.kind() { + ARRAY_TYPE => Type::ArrayType(ArrayType { syntax }), + DYN_TRAIT_TYPE => Type::DynTraitType(DynTraitType { syntax }), + FN_PTR_TYPE => Type::FnPtrType(FnPtrType { syntax }), + FOR_TYPE => Type::ForType(ForType { syntax }), + IMPL_TRAIT_TYPE => Type::ImplTraitType(ImplTraitType { syntax }), + INFER_TYPE => Type::InferType(InferType { syntax }), + NEVER_TYPE => Type::NeverType(NeverType { syntax }), + PAREN_TYPE => Type::ParenType(ParenType { syntax }), + PATH_TYPE => Type::PathType(PathType { syntax }), + PTR_TYPE => Type::PtrType(PtrType { syntax }), + REF_TYPE => Type::RefType(RefType { syntax }), + SLICE_TYPE => Type::SliceType(SliceType { syntax }), + TUPLE_TYPE => Type::TupleType(TupleType { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + Type::ArrayType(it) => &it.syntax, + Type::DynTraitType(it) => &it.syntax, + Type::FnPtrType(it) => &it.syntax, + Type::ForType(it) => &it.syntax, + Type::ImplTraitType(it) => &it.syntax, + Type::InferType(it) => &it.syntax, + Type::NeverType(it) => &it.syntax, + Type::ParenType(it) => &it.syntax, + Type::PathType(it) => &it.syntax, + Type::PtrType(it) => &it.syntax, + Type::RefType(it) => &it.syntax, + Type::SliceType(it) => &it.syntax, + Type::TupleType(it) => &it.syntax, + } + } +} +impl From<ArrayExpr> for Expr { + fn from(node: ArrayExpr) -> Expr { Expr::ArrayExpr(node) } +} +impl From<AwaitExpr> for Expr { + fn from(node: AwaitExpr) -> Expr { Expr::AwaitExpr(node) } +} +impl From<BinExpr> for Expr { + fn from(node: BinExpr) -> Expr { Expr::BinExpr(node) } +} +impl From<BlockExpr> for Expr { + fn from(node: BlockExpr) -> Expr { Expr::BlockExpr(node) } +} +impl From<BoxExpr> for Expr { + fn from(node: BoxExpr) -> Expr { Expr::BoxExpr(node) } +} +impl From<BreakExpr> for Expr { + fn from(node: BreakExpr) -> Expr { Expr::BreakExpr(node) } +} +impl From<CallExpr> for Expr { + fn from(node: CallExpr) -> Expr { Expr::CallExpr(node) } +} +impl From<CastExpr> for Expr { + fn from(node: CastExpr) -> Expr { Expr::CastExpr(node) } +} +impl From<ClosureExpr> for Expr { + fn from(node: ClosureExpr) -> Expr { Expr::ClosureExpr(node) } +} +impl From<ContinueExpr> for Expr { + fn from(node: ContinueExpr) -> Expr { Expr::ContinueExpr(node) } +} +impl From<EffectExpr> for Expr { + fn from(node: EffectExpr) -> Expr { Expr::EffectExpr(node) } +} +impl From<FieldExpr> for Expr { + fn from(node: FieldExpr) -> Expr { Expr::FieldExpr(node) } +} +impl From<ForExpr> for Expr { + fn from(node: ForExpr) -> Expr { Expr::ForExpr(node) } +} +impl From<IfExpr> for Expr { + fn from(node: IfExpr) -> Expr { Expr::IfExpr(node) } +} +impl From<IndexExpr> for Expr { + fn from(node: IndexExpr) -> Expr { Expr::IndexExpr(node) } +} +impl From<Literal> for Expr { + fn from(node: Literal) -> Expr { Expr::Literal(node) } +} +impl From<LoopExpr> for Expr { + fn from(node: LoopExpr) -> Expr { Expr::LoopExpr(node) } +} +impl From<MacroCall> for Expr { + fn from(node: MacroCall) -> Expr { Expr::MacroCall(node) } +} +impl From<MatchExpr> for Expr { + fn from(node: MatchExpr) -> Expr { Expr::MatchExpr(node) } +} +impl From<MethodCallExpr> for Expr { + fn from(node: MethodCallExpr) -> Expr { Expr::MethodCallExpr(node) } +} +impl From<ParenExpr> for Expr { + fn from(node: ParenExpr) -> Expr { Expr::ParenExpr(node) } +} +impl From<PathExpr> for Expr { + fn from(node: PathExpr) -> Expr { Expr::PathExpr(node) } +} +impl From<PrefixExpr> for Expr { + fn from(node: PrefixExpr) -> Expr { Expr::PrefixExpr(node) } +} +impl From<RangeExpr> for Expr { + fn from(node: RangeExpr) -> Expr { Expr::RangeExpr(node) } +} +impl From<RecordExpr> for Expr { + fn from(node: RecordExpr) -> Expr { Expr::RecordExpr(node) } +} +impl From<RefExpr> for Expr { + fn from(node: RefExpr) -> Expr { Expr::RefExpr(node) } +} +impl From<ReturnExpr> for Expr { + fn from(node: ReturnExpr) -> Expr { Expr::ReturnExpr(node) } +} +impl From<TryExpr> for Expr { + fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) } +} +impl From<TupleExpr> for Expr { + fn from(node: TupleExpr) -> Expr { Expr::TupleExpr(node) } +} +impl From<WhileExpr> for Expr { + fn from(node: WhileExpr) -> Expr { Expr::WhileExpr(node) } +} +impl AstNode for Expr { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + ARRAY_EXPR | AWAIT_EXPR | BIN_EXPR | BLOCK_EXPR | BOX_EXPR | BREAK_EXPR | CALL_EXPR + | CAST_EXPR | CLOSURE_EXPR | CONTINUE_EXPR | EFFECT_EXPR | FIELD_EXPR | FOR_EXPR + | IF_EXPR | INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_CALL | MATCH_EXPR + | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR + | RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option<Self> { + let res = match syntax.kind() { + ARRAY_EXPR => Expr::ArrayExpr(ArrayExpr { syntax }), + AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }), + BIN_EXPR => Expr::BinExpr(BinExpr { syntax }), + BLOCK_EXPR => Expr::BlockExpr(BlockExpr { syntax }), + BOX_EXPR => Expr::BoxExpr(BoxExpr { syntax }), + BREAK_EXPR => Expr::BreakExpr(BreakExpr { syntax }), + CALL_EXPR => Expr::CallExpr(CallExpr { syntax }), + CAST_EXPR => Expr::CastExpr(CastExpr { syntax }), + CLOSURE_EXPR => Expr::ClosureExpr(ClosureExpr { syntax }), + CONTINUE_EXPR => Expr::ContinueExpr(ContinueExpr { syntax }), + EFFECT_EXPR => Expr::EffectExpr(EffectExpr { syntax }), + FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }), + FOR_EXPR => Expr::ForExpr(ForExpr { syntax }), + IF_EXPR => Expr::IfExpr(IfExpr { syntax }), + INDEX_EXPR => Expr::IndexExpr(IndexExpr { syntax }), + LITERAL => Expr::Literal(Literal { syntax }), + LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }), + MACRO_CALL => Expr::MacroCall(MacroCall { syntax }), + MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }), + METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }), + PAREN_EXPR => Expr::ParenExpr(ParenExpr { syntax }), + PATH_EXPR => Expr::PathExpr(PathExpr { syntax }), + PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }), + RANGE_EXPR => Expr::RangeExpr(RangeExpr { syntax }), + RECORD_EXPR => Expr::RecordExpr(RecordExpr { syntax }), + REF_EXPR => Expr::RefExpr(RefExpr { syntax }), + RETURN_EXPR => Expr::ReturnExpr(ReturnExpr { syntax }), + TRY_EXPR => Expr::TryExpr(TryExpr { syntax }), + TUPLE_EXPR => Expr::TupleExpr(TupleExpr { syntax }), + WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + Expr::ArrayExpr(it) => &it.syntax, + Expr::AwaitExpr(it) => &it.syntax, + Expr::BinExpr(it) => &it.syntax, + Expr::BlockExpr(it) => &it.syntax, + Expr::BoxExpr(it) => &it.syntax, + Expr::BreakExpr(it) => &it.syntax, + Expr::CallExpr(it) => &it.syntax, + Expr::CastExpr(it) => &it.syntax, + Expr::ClosureExpr(it) => &it.syntax, + Expr::ContinueExpr(it) => &it.syntax, + Expr::EffectExpr(it) => &it.syntax, + Expr::FieldExpr(it) => &it.syntax, + Expr::ForExpr(it) => &it.syntax, + Expr::IfExpr(it) => &it.syntax, + Expr::IndexExpr(it) => &it.syntax, + Expr::Literal(it) => &it.syntax, + Expr::LoopExpr(it) => &it.syntax, + Expr::MacroCall(it) => &it.syntax, + Expr::MatchExpr(it) => &it.syntax, + Expr::MethodCallExpr(it) => &it.syntax, + Expr::ParenExpr(it) => &it.syntax, + Expr::PathExpr(it) => &it.syntax, + Expr::PrefixExpr(it) => &it.syntax, + Expr::RangeExpr(it) => &it.syntax, + Expr::RecordExpr(it) => &it.syntax, + Expr::RefExpr(it) => &it.syntax, + Expr::ReturnExpr(it) => &it.syntax, + Expr::TryExpr(it) => &it.syntax, + Expr::TupleExpr(it) => &it.syntax, + Expr::WhileExpr(it) => &it.syntax, + } + } +} +impl From<Const> for Item { + fn from(node: Const) -> Item { Item::Const(node) } +} +impl From<Enum> for Item { + fn from(node: Enum) -> Item { Item::Enum(node) } +} +impl From<ExternBlock> for Item { + fn from(node: ExternBlock) -> Item { Item::ExternBlock(node) } +} +impl From<ExternCrate> for Item { + fn from(node: ExternCrate) -> Item { Item::ExternCrate(node) } +} +impl From<Fn> for Item { + fn from(node: Fn) -> Item { Item::Fn(node) } +} +impl From<Impl> for Item { + fn from(node: Impl) -> Item { Item::Impl(node) } +} +impl From<MacroCall> for Item { + fn from(node: MacroCall) -> Item { Item::MacroCall(node) } +} +impl From<Module> for Item { + fn from(node: Module) -> Item { Item::Module(node) } +} +impl From<Static> for Item { + fn from(node: Static) -> Item { Item::Static(node) } +} +impl From<Struct> for Item { + fn from(node: Struct) -> Item { Item::Struct(node) } +} +impl From<Trait> for Item { + fn from(node: Trait) -> Item { Item::Trait(node) } +} +impl From<TypeAlias> for Item { + fn from(node: TypeAlias) -> Item { Item::TypeAlias(node) } +} +impl From<Union> for Item { + fn from(node: Union) -> Item { Item::Union(node) } +} +impl From<Use> for Item { + fn from(node: Use) -> Item { Item::Use(node) } +} +impl AstNode for Item { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL | MACRO_CALL | MODULE + | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option<Self> { + let res = match syntax.kind() { + CONST => Item::Const(Const { syntax }), + ENUM => Item::Enum(Enum { syntax }), + EXTERN_BLOCK => Item::ExternBlock(ExternBlock { syntax }), + EXTERN_CRATE => Item::ExternCrate(ExternCrate { syntax }), + FN => Item::Fn(Fn { syntax }), + IMPL => Item::Impl(Impl { syntax }), + MACRO_CALL => Item::MacroCall(MacroCall { syntax }), + MODULE => Item::Module(Module { syntax }), + STATIC => Item::Static(Static { syntax }), + STRUCT => Item::Struct(Struct { syntax }), + TRAIT => Item::Trait(Trait { syntax }), + TYPE_ALIAS => Item::TypeAlias(TypeAlias { syntax }), + UNION => Item::Union(Union { syntax }), + USE => Item::Use(Use { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + Item::Const(it) => &it.syntax, + Item::Enum(it) => &it.syntax, + Item::ExternBlock(it) => &it.syntax, + Item::ExternCrate(it) => &it.syntax, + Item::Fn(it) => &it.syntax, + Item::Impl(it) => &it.syntax, + Item::MacroCall(it) => &it.syntax, + Item::Module(it) => &it.syntax, + Item::Static(it) => &it.syntax, + Item::Struct(it) => &it.syntax, + Item::Trait(it) => &it.syntax, + Item::TypeAlias(it) => &it.syntax, + Item::Union(it) => &it.syntax, + Item::Use(it) => &it.syntax, + } + } +} +impl From<ExprStmt> for Stmt { + fn from(node: ExprStmt) -> Stmt { Stmt::ExprStmt(node) } +} +impl From<Item> for Stmt { + fn from(node: Item) -> Stmt { Stmt::Item(node) } +} +impl From<LetStmt> for Stmt { + fn from(node: LetStmt) -> Stmt { Stmt::LetStmt(node) } +} +impl From<IdentPat> for Pat { + fn from(node: IdentPat) -> Pat { Pat::IdentPat(node) } +} +impl From<BoxPat> for Pat { + fn from(node: BoxPat) -> Pat { Pat::BoxPat(node) } +} +impl From<RestPat> for Pat { + fn from(node: RestPat) -> Pat { Pat::RestPat(node) } +} +impl From<LiteralPat> for Pat { + fn from(node: LiteralPat) -> Pat { Pat::LiteralPat(node) } +} +impl From<MacroPat> for Pat { + fn from(node: MacroPat) -> Pat { Pat::MacroPat(node) } +} +impl From<OrPat> for Pat { + fn from(node: OrPat) -> Pat { Pat::OrPat(node) } +} +impl From<ParenPat> for Pat { + fn from(node: ParenPat) -> Pat { Pat::ParenPat(node) } +} +impl From<PathPat> for Pat { + fn from(node: PathPat) -> Pat { Pat::PathPat(node) } +} +impl From<WildcardPat> for Pat { + fn from(node: WildcardPat) -> Pat { Pat::WildcardPat(node) } +} +impl From<RangePat> for Pat { + fn from(node: RangePat) -> Pat { Pat::RangePat(node) } +} +impl From<RecordPat> for Pat { + fn from(node: RecordPat) -> Pat { Pat::RecordPat(node) } +} +impl From<RefPat> for Pat { + fn from(node: RefPat) -> Pat { Pat::RefPat(node) } +} +impl From<SlicePat> for Pat { + fn from(node: SlicePat) -> Pat { Pat::SlicePat(node) } +} +impl From<TuplePat> for Pat { + fn from(node: TuplePat) -> Pat { Pat::TuplePat(node) } +} +impl From<TupleStructPat> for Pat { + fn from(node: TupleStructPat) -> Pat { Pat::TupleStructPat(node) } +} +impl AstNode for Pat { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + IDENT_PAT | BOX_PAT | REST_PAT | LITERAL_PAT | MACRO_PAT | OR_PAT | PAREN_PAT + | PATH_PAT | WILDCARD_PAT | RANGE_PAT | RECORD_PAT | REF_PAT | SLICE_PAT + | TUPLE_PAT | TUPLE_STRUCT_PAT => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option<Self> { + let res = match syntax.kind() { + IDENT_PAT => Pat::IdentPat(IdentPat { syntax }), + BOX_PAT => Pat::BoxPat(BoxPat { syntax }), + REST_PAT => Pat::RestPat(RestPat { syntax }), + LITERAL_PAT => Pat::LiteralPat(LiteralPat { syntax }), + MACRO_PAT => Pat::MacroPat(MacroPat { syntax }), + OR_PAT => Pat::OrPat(OrPat { syntax }), + PAREN_PAT => Pat::ParenPat(ParenPat { syntax }), + PATH_PAT => Pat::PathPat(PathPat { syntax }), + WILDCARD_PAT => Pat::WildcardPat(WildcardPat { syntax }), + RANGE_PAT => Pat::RangePat(RangePat { syntax }), + RECORD_PAT => Pat::RecordPat(RecordPat { syntax }), + REF_PAT => Pat::RefPat(RefPat { syntax }), + SLICE_PAT => Pat::SlicePat(SlicePat { syntax }), + TUPLE_PAT => Pat::TuplePat(TuplePat { syntax }), + TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + Pat::IdentPat(it) => &it.syntax, + Pat::BoxPat(it) => &it.syntax, + Pat::RestPat(it) => &it.syntax, + Pat::LiteralPat(it) => &it.syntax, + Pat::MacroPat(it) => &it.syntax, + Pat::OrPat(it) => &it.syntax, + Pat::ParenPat(it) => &it.syntax, + Pat::PathPat(it) => &it.syntax, + Pat::WildcardPat(it) => &it.syntax, + Pat::RangePat(it) => &it.syntax, + Pat::RecordPat(it) => &it.syntax, + Pat::RefPat(it) => &it.syntax, + Pat::SlicePat(it) => &it.syntax, + Pat::TuplePat(it) => &it.syntax, + Pat::TupleStructPat(it) => &it.syntax, + } + } +} +impl From<RecordFieldList> for FieldList { + fn from(node: RecordFieldList) -> FieldList { FieldList::RecordFieldList(node) } +} +impl From<TupleFieldList> for FieldList { + fn from(node: TupleFieldList) -> FieldList { FieldList::TupleFieldList(node) } +} +impl AstNode for FieldList { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + RECORD_FIELD_LIST | TUPLE_FIELD_LIST => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option<Self> { + let res = match syntax.kind() { + RECORD_FIELD_LIST => FieldList::RecordFieldList(RecordFieldList { syntax }), + TUPLE_FIELD_LIST => FieldList::TupleFieldList(TupleFieldList { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + FieldList::RecordFieldList(it) => &it.syntax, + FieldList::TupleFieldList(it) => &it.syntax, + } + } +} +impl From<Enum> for AdtDef { + fn from(node: Enum) -> AdtDef { AdtDef::Enum(node) } +} +impl From<Struct> for AdtDef { + fn from(node: Struct) -> AdtDef { AdtDef::Struct(node) } +} +impl From<Union> for AdtDef { + fn from(node: Union) -> AdtDef { AdtDef::Union(node) } +} +impl AstNode for AdtDef { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + ENUM | STRUCT | UNION => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option<Self> { + let res = match syntax.kind() { + ENUM => AdtDef::Enum(Enum { syntax }), + STRUCT => AdtDef::Struct(Struct { syntax }), + UNION => AdtDef::Union(Union { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + AdtDef::Enum(it) => &it.syntax, + AdtDef::Struct(it) => &it.syntax, + AdtDef::Union(it) => &it.syntax, + } + } +} +impl From<Const> for AssocItem { + fn from(node: Const) -> AssocItem { AssocItem::Const(node) } +} +impl From<Fn> for AssocItem { + fn from(node: Fn) -> AssocItem { AssocItem::Fn(node) } +} +impl From<MacroCall> for AssocItem { + fn from(node: MacroCall) -> AssocItem { AssocItem::MacroCall(node) } +} +impl From<TypeAlias> for AssocItem { + fn from(node: TypeAlias) -> AssocItem { AssocItem::TypeAlias(node) } +} +impl AstNode for AssocItem { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + CONST | FN | MACRO_CALL | TYPE_ALIAS => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option<Self> { + let res = match syntax.kind() { + CONST => AssocItem::Const(Const { syntax }), + FN => AssocItem::Fn(Fn { syntax }), + MACRO_CALL => AssocItem::MacroCall(MacroCall { syntax }), + TYPE_ALIAS => AssocItem::TypeAlias(TypeAlias { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + AssocItem::Const(it) => &it.syntax, + AssocItem::Fn(it) => &it.syntax, + AssocItem::MacroCall(it) => &it.syntax, + AssocItem::TypeAlias(it) => &it.syntax, + } + } +} +impl From<Fn> for ExternItem { + fn from(node: Fn) -> ExternItem { ExternItem::Fn(node) } +} +impl From<MacroCall> for ExternItem { + fn from(node: MacroCall) -> ExternItem { ExternItem::MacroCall(node) } +} +impl From<Static> for ExternItem { + fn from(node: Static) -> ExternItem { ExternItem::Static(node) } +} +impl AstNode for ExternItem { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + FN | MACRO_CALL | STATIC => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option<Self> { + let res = match syntax.kind() { + FN => ExternItem::Fn(Fn { syntax }), + MACRO_CALL => ExternItem::MacroCall(MacroCall { syntax }), + STATIC => ExternItem::Static(Static { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + ExternItem::Fn(it) => &it.syntax, + ExternItem::MacroCall(it) => &it.syntax, + ExternItem::Static(it) => &it.syntax, + } + } +} +impl From<ConstParam> for GenericParam { + fn from(node: ConstParam) -> GenericParam { GenericParam::ConstParam(node) } +} +impl From<LifetimeParam> for GenericParam { + fn from(node: LifetimeParam) -> GenericParam { GenericParam::LifetimeParam(node) } +} +impl From<TypeParam> for GenericParam { + fn from(node: TypeParam) -> GenericParam { GenericParam::TypeParam(node) } +} +impl AstNode for GenericParam { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + CONST_PARAM | LIFETIME_PARAM | TYPE_PARAM => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option<Self> { + let res = match syntax.kind() { + CONST_PARAM => GenericParam::ConstParam(ConstParam { syntax }), + LIFETIME_PARAM => GenericParam::LifetimeParam(LifetimeParam { syntax }), + TYPE_PARAM => GenericParam::TypeParam(TypeParam { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + GenericParam::ConstParam(it) => &it.syntax, + GenericParam::LifetimeParam(it) => &it.syntax, + GenericParam::TypeParam(it) => &it.syntax, + } + } +} +impl std::fmt::Display for GenericArg { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Type { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Expr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Item { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Stmt { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Pat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for FieldList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for AdtDef { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for AssocItem { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ExternItem { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for GenericParam { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +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 std::fmt::Display for NameRef { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Path { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for PathSegment { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for GenericArgList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ParamList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RetType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for PathType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for TypeArg { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for AssocTypeArg { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for LifetimeArg { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ConstArg { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for TypeBoundList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for MacroCall { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Attr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for TokenTree { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for MacroItems { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for MacroStmts { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for SourceFile { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Const { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Enum { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ExternBlock { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ExternCrate { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Fn { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Impl { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Module { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Static { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Struct { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Trait { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for TypeAlias { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Union { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Use { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Visibility { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ItemList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Rename { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for UseTree { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for UseTreeList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Abi { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for GenericParamList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for WhereClause { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for BlockExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for SelfParam { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Param { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RecordFieldList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for TupleFieldList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RecordField { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for TupleField { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for VariantList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Variant { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for AssocItemList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ExternItemList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ConstParam { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for LifetimeParam { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for TypeParam { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for WherePred { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Literal { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ExprStmt { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for LetStmt { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ArrayExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for AwaitExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for BinExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for BoxExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for BreakExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for CallExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for CastExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ClosureExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ContinueExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for EffectExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for FieldExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ForExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for IfExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for IndexExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for LoopExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for MatchExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for MethodCallExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ParenExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for PathExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for PrefixExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RangeExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RecordExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RefExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ReturnExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for TryExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for TupleExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for WhileExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Label { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RecordExprFieldList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RecordExprField { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ArgList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Condition { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for MatchArmList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for MatchArm { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for MatchGuard { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ArrayType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for DynTraitType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for FnPtrType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ForType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ImplTraitType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for InferType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for NeverType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ParenType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for PtrType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RefType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for SliceType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for TupleType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for TypeBound { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for IdentPat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for BoxPat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RestPat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for LiteralPat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for MacroPat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for OrPat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for ParenPat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for PathPat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for WildcardPat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RangePat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RecordPat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RefPat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for SlicePat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for TuplePat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for TupleStructPat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RecordPatFieldList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for RecordPatField { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} diff --git a/crates/syntax/src/ast/generated/tokens.rs b/crates/syntax/src/ast/generated/tokens.rs new file mode 100644 index 00000000000..abadd0b61c6 --- /dev/null +++ b/crates/syntax/src/ast/generated/tokens.rs @@ -0,0 +1,91 @@ +//! Generated file, do not edit by hand, see `xtask/src/codegen` + +use crate::{ + ast::AstToken, + SyntaxKind::{self, *}, + SyntaxToken, +}; + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Whitespace { + pub(crate) syntax: SyntaxToken, +} +impl std::fmt::Display for Whitespace { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(&self.syntax, f) + } +} +impl AstToken for Whitespace { + fn can_cast(kind: SyntaxKind) -> bool { kind == WHITESPACE } + fn cast(syntax: SyntaxToken) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxToken { &self.syntax } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Comment { + pub(crate) syntax: SyntaxToken, +} +impl std::fmt::Display for Comment { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(&self.syntax, f) + } +} +impl AstToken for Comment { + fn can_cast(kind: SyntaxKind) -> bool { kind == COMMENT } + fn cast(syntax: SyntaxToken) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxToken { &self.syntax } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct String { + pub(crate) syntax: SyntaxToken, +} +impl std::fmt::Display for String { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(&self.syntax, f) + } +} +impl AstToken for String { + fn can_cast(kind: SyntaxKind) -> bool { kind == STRING } + fn cast(syntax: SyntaxToken) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxToken { &self.syntax } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RawString { + pub(crate) syntax: SyntaxToken, +} +impl std::fmt::Display for RawString { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(&self.syntax, f) + } +} +impl AstToken for RawString { + fn can_cast(kind: SyntaxKind) -> bool { kind == RAW_STRING } + fn cast(syntax: SyntaxToken) -> Option<Self> { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxToken { &self.syntax } +} diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs new file mode 100644 index 00000000000..254a37fe3e4 --- /dev/null +++ b/crates/syntax/src/ast/make.rs @@ -0,0 +1,392 @@ +//! This module contains free-standing functions for creating AST fragments out +//! of smaller pieces. +//! +//! Note that all functions here intended to be stupid constructors, which just +//! assemble a finish node from immediate children. If you want to do something +//! smarter than that, it probably doesn't belong in this module. +use itertools::Itertools; +use stdx::format_to; + +use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken}; + +pub fn name(text: &str) -> ast::Name { + ast_from_text(&format!("mod {};", text)) +} + +pub fn name_ref(text: &str) -> ast::NameRef { + ast_from_text(&format!("fn f() {{ {}; }}", text)) +} + +pub fn ty(text: &str) -> ast::Type { + ast_from_text(&format!("impl {} for D {{}};", text)) +} + +pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment { + ast_from_text(&format!("use {};", name_ref)) +} +pub fn path_unqualified(segment: ast::PathSegment) -> ast::Path { + path_from_text(&format!("use {}", segment)) +} +pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path { + path_from_text(&format!("{}::{}", qual, segment)) +} +pub fn path_from_text(text: &str) -> ast::Path { + ast_from_text(text) +} + +pub fn use_tree( + path: ast::Path, + use_tree_list: Option<ast::UseTreeList>, + alias: Option<ast::Rename>, + add_star: bool, +) -> ast::UseTree { + let mut buf = "use ".to_string(); + buf += &path.syntax().to_string(); + if let Some(use_tree_list) = use_tree_list { + format_to!(buf, "::{}", use_tree_list); + } + if add_star { + buf += "::*"; + } + + if let Some(alias) = alias { + format_to!(buf, " {}", alias); + } + ast_from_text(&buf) +} + +pub fn use_tree_list(use_trees: impl IntoIterator<Item = ast::UseTree>) -> ast::UseTreeList { + let use_trees = use_trees.into_iter().map(|it| it.syntax().clone()).join(", "); + ast_from_text(&format!("use {{{}}};", use_trees)) +} + +pub fn use_(use_tree: ast::UseTree) -> ast::Use { + ast_from_text(&format!("use {};", use_tree)) +} + +pub fn record_expr_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordExprField { + return match expr { + Some(expr) => from_text(&format!("{}: {}", name, expr)), + None => from_text(&name.to_string()), + }; + + fn from_text(text: &str) -> ast::RecordExprField { + ast_from_text(&format!("fn f() {{ S {{ {}, }} }}", text)) + } +} + +pub fn record_field(name: ast::NameRef, ty: ast::Type) -> ast::RecordField { + ast_from_text(&format!("struct S {{ {}: {}, }}", name, ty)) +} + +pub fn block_expr( + stmts: impl IntoIterator<Item = ast::Stmt>, + tail_expr: Option<ast::Expr>, +) -> ast::BlockExpr { + let mut buf = "{\n".to_string(); + for stmt in stmts.into_iter() { + format_to!(buf, " {}\n", stmt); + } + if let Some(tail_expr) = tail_expr { + format_to!(buf, " {}\n", tail_expr) + } + buf += "}"; + ast_from_text(&format!("fn f() {}", buf)) +} + +pub fn expr_unit() -> ast::Expr { + expr_from_text("()") +} +pub fn expr_empty_block() -> ast::Expr { + expr_from_text("{}") +} +pub fn expr_unimplemented() -> ast::Expr { + expr_from_text("unimplemented!()") +} +pub fn expr_unreachable() -> ast::Expr { + expr_from_text("unreachable!()") +} +pub fn expr_todo() -> ast::Expr { + expr_from_text("todo!()") +} +pub fn expr_path(path: ast::Path) -> ast::Expr { + expr_from_text(&path.to_string()) +} +pub fn expr_continue() -> ast::Expr { + expr_from_text("continue") +} +pub fn expr_break() -> ast::Expr { + expr_from_text("break") +} +pub fn expr_return() -> ast::Expr { + expr_from_text("return") +} +pub fn expr_match(expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::Expr { + expr_from_text(&format!("match {} {}", expr, match_arm_list)) +} +pub fn expr_if(condition: ast::Condition, then_branch: ast::BlockExpr) -> ast::Expr { + expr_from_text(&format!("if {} {}", condition, then_branch)) +} +pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr { + let token = token(op); + expr_from_text(&format!("{}{}", token, expr)) +} +fn expr_from_text(text: &str) -> ast::Expr { + ast_from_text(&format!("const C: () = {};", text)) +} + +pub fn try_expr_from_text(text: &str) -> Option<ast::Expr> { + try_ast_from_text(&format!("const C: () = {};", text)) +} + +pub fn condition(expr: ast::Expr, pattern: Option<ast::Pat>) -> ast::Condition { + match pattern { + None => ast_from_text(&format!("const _: () = while {} {{}};", expr)), + Some(pattern) => { + ast_from_text(&format!("const _: () = while let {} = {} {{}};", pattern, expr)) + } + } +} + +pub fn ident_pat(name: ast::Name) -> ast::IdentPat { + return from_text(name.text()); + + fn from_text(text: &str) -> ast::IdentPat { + ast_from_text(&format!("fn f({}: ())", text)) + } +} + +pub fn wildcard_pat() -> ast::WildcardPat { + return from_text("_"); + + fn from_text(text: &str) -> ast::WildcardPat { + ast_from_text(&format!("fn f({}: ())", text)) + } +} + +/// Creates a tuple of patterns from an interator of patterns. +/// +/// Invariant: `pats` must be length > 1 +/// +/// FIXME handle `pats` length == 1 +pub fn tuple_pat(pats: impl IntoIterator<Item = ast::Pat>) -> ast::TuplePat { + let pats_str = pats.into_iter().map(|p| p.to_string()).join(", "); + return from_text(&format!("({})", pats_str)); + + fn from_text(text: &str) -> ast::TuplePat { + ast_from_text(&format!("fn f({}: ())", text)) + } +} + +pub fn tuple_struct_pat( + path: ast::Path, + pats: impl IntoIterator<Item = ast::Pat>, +) -> ast::TupleStructPat { + let pats_str = pats.into_iter().join(", "); + return from_text(&format!("{}({})", path, pats_str)); + + fn from_text(text: &str) -> ast::TupleStructPat { + ast_from_text(&format!("fn f({}: ())", text)) + } +} + +pub fn record_pat(path: ast::Path, pats: impl IntoIterator<Item = ast::Pat>) -> ast::RecordPat { + let pats_str = pats.into_iter().join(", "); + return from_text(&format!("{} {{ {} }}", path, pats_str)); + + fn from_text(text: &str) -> ast::RecordPat { + ast_from_text(&format!("fn f({}: ())", text)) + } +} + +/// Returns a `BindPat` if the path has just one segment, a `PathPat` otherwise. +pub fn path_pat(path: ast::Path) -> ast::Pat { + return from_text(&path.to_string()); + fn from_text(text: &str) -> ast::Pat { + ast_from_text(&format!("fn f({}: ())", text)) + } +} + +pub fn match_arm(pats: impl IntoIterator<Item = ast::Pat>, expr: ast::Expr) -> ast::MatchArm { + let pats_str = pats.into_iter().join(" | "); + return from_text(&format!("{} => {}", pats_str, expr)); + + fn from_text(text: &str) -> ast::MatchArm { + ast_from_text(&format!("fn f() {{ match () {{{}}} }}", text)) + } +} + +pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::MatchArmList { + let arms_str = arms + .into_iter() + .map(|arm| { + let needs_comma = arm.expr().map_or(true, |it| !it.is_block_like()); + let comma = if needs_comma { "," } else { "" }; + format!(" {}{}\n", arm.syntax(), comma) + }) + .collect::<String>(); + return from_text(&arms_str); + + fn from_text(text: &str) -> ast::MatchArmList { + ast_from_text(&format!("fn f() {{ match () {{\n{}}} }}", text)) + } +} + +pub fn where_pred( + path: ast::Path, + bounds: impl IntoIterator<Item = ast::TypeBound>, +) -> ast::WherePred { + let bounds = bounds.into_iter().join(" + "); + return from_text(&format!("{}: {}", path, bounds)); + + fn from_text(text: &str) -> ast::WherePred { + ast_from_text(&format!("fn f() where {} {{ }}", text)) + } +} + +pub fn where_clause(preds: impl IntoIterator<Item = ast::WherePred>) -> ast::WhereClause { + let preds = preds.into_iter().join(", "); + return from_text(preds.as_str()); + + fn from_text(text: &str) -> ast::WhereClause { + ast_from_text(&format!("fn f() where {} {{ }}", text)) + } +} + +pub fn let_stmt(pattern: ast::Pat, initializer: Option<ast::Expr>) -> ast::LetStmt { + let text = match initializer { + Some(it) => format!("let {} = {};", pattern, it), + None => format!("let {};", pattern), + }; + ast_from_text(&format!("fn f() {{ {} }}", text)) +} +pub fn expr_stmt(expr: ast::Expr) -> ast::ExprStmt { + let semi = if expr.is_block_like() { "" } else { ";" }; + ast_from_text(&format!("fn f() {{ {}{} (); }}", expr, semi)) +} + +pub fn token(kind: SyntaxKind) -> SyntaxToken { + tokens::SOURCE_FILE + .tree() + .syntax() + .descendants_with_tokens() + .filter_map(|it| it.into_token()) + .find(|it| it.kind() == kind) + .unwrap_or_else(|| panic!("unhandled token: {:?}", kind)) +} + +pub fn param(name: String, ty: String) -> ast::Param { + ast_from_text(&format!("fn f({}: {}) {{ }}", name, ty)) +} + +pub fn param_list(pats: impl IntoIterator<Item = ast::Param>) -> ast::ParamList { + let args = pats.into_iter().join(", "); + ast_from_text(&format!("fn f({}) {{ }}", args)) +} + +pub fn visibility_pub_crate() -> ast::Visibility { + ast_from_text("pub(crate) struct S") +} + +pub fn fn_( + visibility: Option<ast::Visibility>, + fn_name: ast::Name, + type_params: Option<ast::GenericParamList>, + params: ast::ParamList, + body: ast::BlockExpr, +) -> ast::Fn { + let type_params = + if let Some(type_params) = type_params { format!("<{}>", type_params) } else { "".into() }; + let visibility = match visibility { + None => String::new(), + Some(it) => format!("{} ", it), + }; + ast_from_text(&format!("{}fn {}{}{} {}", visibility, fn_name, type_params, params, body)) +} + +fn ast_from_text<N: AstNode>(text: &str) -> N { + let parse = SourceFile::parse(text); + let node = match parse.tree().syntax().descendants().find_map(N::cast) { + Some(it) => it, + None => { + panic!("Failed to make ast node `{}` from text {}", std::any::type_name::<N>(), text) + } + }; + let node = node.syntax().clone(); + let node = unroot(node); + let node = N::cast(node).unwrap(); + assert_eq!(node.syntax().text_range().start(), 0.into()); + node +} + +fn try_ast_from_text<N: AstNode>(text: &str) -> Option<N> { + let parse = SourceFile::parse(text); + let node = parse.tree().syntax().descendants().find_map(N::cast)?; + let node = node.syntax().clone(); + let node = unroot(node); + let node = N::cast(node).unwrap(); + assert_eq!(node.syntax().text_range().start(), 0.into()); + Some(node) +} + +fn unroot(n: SyntaxNode) -> SyntaxNode { + SyntaxNode::new_root(n.green().clone()) +} + +pub mod tokens { + use once_cell::sync::Lazy; + + use crate::{ast, AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken}; + + pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> = + Lazy::new(|| SourceFile::parse("const C: <()>::Item = (1 != 1, 2 == 2, !true)\n;")); + + pub fn single_space() -> SyntaxToken { + SOURCE_FILE + .tree() + .syntax() + .descendants_with_tokens() + .filter_map(|it| it.into_token()) + .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ") + .unwrap() + } + + pub fn whitespace(text: &str) -> SyntaxToken { + assert!(text.trim().is_empty()); + let sf = SourceFile::parse(text).ok().unwrap(); + sf.syntax().first_child_or_token().unwrap().into_token().unwrap() + } + + pub fn doc_comment(text: &str) -> SyntaxToken { + assert!(!text.trim().is_empty()); + let sf = SourceFile::parse(text).ok().unwrap(); + sf.syntax().first_child_or_token().unwrap().into_token().unwrap() + } + + pub fn literal(text: &str) -> SyntaxToken { + assert_eq!(text.trim(), text); + let lit: ast::Literal = super::ast_from_text(&format!("fn f() {{ let _ = {}; }}", text)); + lit.syntax().first_child_or_token().unwrap().into_token().unwrap() + } + + pub fn single_newline() -> SyntaxToken { + SOURCE_FILE + .tree() + .syntax() + .descendants_with_tokens() + .filter_map(|it| it.into_token()) + .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n") + .unwrap() + } + + pub struct WsBuilder(SourceFile); + + impl WsBuilder { + pub fn new(text: &str) -> WsBuilder { + WsBuilder(SourceFile::parse(text).ok().unwrap()) + } + pub fn ws(&self) -> SyntaxToken { + self.0.syntax().first_child_or_token().unwrap().into_token().unwrap() + } + } +} diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs new file mode 100644 index 00000000000..50c1c157d87 --- /dev/null +++ b/crates/syntax/src/ast/node_ext.rs @@ -0,0 +1,485 @@ +//! 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::fmt; + +use itertools::Itertools; +use parser::SyntaxKind; + +use crate::{ + ast::{self, support, AstNode, NameOwner, SyntaxNode}, + SmolStr, SyntaxElement, SyntaxToken, T, +}; + +impl ast::Name { + pub fn text(&self) -> &SmolStr { + text_of_first_token(self.syntax()) + } +} + +impl ast::NameRef { + pub fn text(&self) -> &SmolStr { + 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) -> &SmolStr { + node.green().children().next().and_then(|it| it.into_token()).unwrap().text() +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum AttrKind { + Inner, + Outer, +} + +impl ast::Attr { + pub fn as_simple_atom(&self) -> Option<SmolStr> { + if self.eq_token().is_some() || self.token_tree().is_some() { + return None; + } + self.simple_name() + } + + pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> { + let tt = self.token_tree()?; + Some((self.simple_name()?, tt)) + } + + pub fn as_simple_key_value(&self) -> Option<(SmolStr, SmolStr)> { + let lit = self.literal()?; + let key = self.simple_name()?; + // FIXME: escape? raw string? + let value = lit.syntax().first_token()?.text().trim_matches('"').into(); + Some((key, value)) + } + + pub fn simple_name(&self) -> Option<SmolStr> { + let path = self.path()?; + match (path.segment(), path.qualifier()) { + (Some(segment), None) => Some(segment.syntax().first_token()?.text().clone()), + _ => None, + } + } + + pub fn kind(&self) -> AttrKind { + let first_token = self.syntax().first_token(); + let first_token_kind = first_token.as_ref().map(SyntaxToken::kind); + let second_token_kind = + first_token.and_then(|token| token.next_token()).as_ref().map(SyntaxToken::kind); + + match (first_token_kind, second_token_kind) { + (Some(SyntaxKind::POUND), Some(T![!])) => AttrKind::Inner, + _ => AttrKind::Outer, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum PathSegmentKind { + Name(ast::NameRef), + Type { type_ref: Option<ast::Type>, trait_ref: Option<ast::PathType> }, + SelfKw, + SuperKw, + CrateKw, +} + +impl ast::PathSegment { + pub fn parent_path(&self) -> ast::Path { + self.syntax() + .parent() + .and_then(ast::Path::cast) + .expect("segments are always nested in paths") + } + + pub fn kind(&self) -> Option<PathSegmentKind> { + let res = if let Some(name_ref) = self.name_ref() { + PathSegmentKind::Name(name_ref) + } else { + match self.syntax().first_child_or_token()?.kind() { + T![self] => PathSegmentKind::SelfKw, + T![super] => PathSegmentKind::SuperKw, + T![crate] => PathSegmentKind::CrateKw, + T![<] => { + // <T> or <T as Trait> + // T is any TypeRef, Trait has to be a PathType + let mut type_refs = + self.syntax().children().filter(|node| ast::Type::can_cast(node.kind())); + let type_ref = type_refs.next().and_then(ast::Type::cast); + let trait_ref = type_refs.next().and_then(ast::PathType::cast); + PathSegmentKind::Type { type_ref, trait_ref } + } + _ => return None, + } + }; + Some(res) + } +} + +impl ast::Path { + pub fn parent_path(&self) -> Option<ast::Path> { + self.syntax().parent().and_then(ast::Path::cast) + } +} + +impl ast::UseTreeList { + pub fn parent_use_tree(&self) -> ast::UseTree { + self.syntax() + .parent() + .and_then(ast::UseTree::cast) + .expect("UseTreeLists are always nested in UseTrees") + } +} + +impl ast::Impl { + pub fn self_ty(&self) -> Option<ast::Type> { + match self.target() { + (Some(t), None) | (_, Some(t)) => Some(t), + _ => None, + } + } + + pub fn trait_(&self) -> Option<ast::Type> { + match self.target() { + (Some(t), Some(_)) => Some(t), + _ => None, + } + } + + fn target(&self) -> (Option<ast::Type>, Option<ast::Type>) { + let mut types = support::children(self.syntax()); + let first = types.next(); + let second = types.next(); + (first, second) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum StructKind { + Record(ast::RecordFieldList), + Tuple(ast::TupleFieldList), + Unit, +} + +impl StructKind { + fn from_node<N: AstNode>(node: &N) -> StructKind { + if let Some(nfdl) = support::child::<ast::RecordFieldList>(node.syntax()) { + StructKind::Record(nfdl) + } else if let Some(pfl) = support::child::<ast::TupleFieldList>(node.syntax()) { + StructKind::Tuple(pfl) + } else { + StructKind::Unit + } + } +} + +impl ast::Struct { + pub fn kind(&self) -> StructKind { + StructKind::from_node(self) + } +} + +impl ast::RecordExprField { + pub fn for_field_name(field_name: &ast::NameRef) -> Option<ast::RecordExprField> { + let candidate = + field_name.syntax().parent().and_then(ast::RecordExprField::cast).or_else(|| { + field_name.syntax().ancestors().nth(4).and_then(ast::RecordExprField::cast) + })?; + if candidate.field_name().as_ref() == Some(field_name) { + Some(candidate) + } else { + None + } + } + + /// Deals with field init shorthand + pub fn field_name(&self) -> Option<ast::NameRef> { + if let Some(name_ref) = self.name_ref() { + return Some(name_ref); + } + if let Some(ast::Expr::PathExpr(expr)) = self.expr() { + let path = expr.path()?; + let segment = path.segment()?; + let name_ref = segment.name_ref()?; + if path.qualifier().is_none() { + return Some(name_ref); + } + } + None + } +} + +pub enum NameOrNameRef { + Name(ast::Name), + NameRef(ast::NameRef), +} + +impl fmt::Display for NameOrNameRef { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + NameOrNameRef::Name(it) => fmt::Display::fmt(it, f), + NameOrNameRef::NameRef(it) => fmt::Display::fmt(it, f), + } + } +} + +impl ast::RecordPatField { + /// Deals with field init shorthand + pub fn field_name(&self) -> Option<NameOrNameRef> { + if let Some(name_ref) = self.name_ref() { + return Some(NameOrNameRef::NameRef(name_ref)); + } + if let Some(ast::Pat::IdentPat(pat)) = self.pat() { + let name = pat.name()?; + return Some(NameOrNameRef::Name(name)); + } + None + } +} + +impl ast::Variant { + pub fn parent_enum(&self) -> ast::Enum { + self.syntax() + .parent() + .and_then(|it| it.parent()) + .and_then(ast::Enum::cast) + .expect("EnumVariants are always nested in Enums") + } + pub fn kind(&self) -> StructKind { + StructKind::from_node(self) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum FieldKind { + Name(ast::NameRef), + Index(SyntaxToken), +} + +impl ast::FieldExpr { + pub fn index_token(&self) -> Option<SyntaxToken> { + self.syntax + .children_with_tokens() + // FIXME: Accepting floats here to reject them in validation later + .find(|c| c.kind() == SyntaxKind::INT_NUMBER || c.kind() == SyntaxKind::FLOAT_NUMBER) + .as_ref() + .and_then(SyntaxElement::as_token) + .cloned() + } + + pub fn field_access(&self) -> Option<FieldKind> { + if let Some(nr) = self.name_ref() { + Some(FieldKind::Name(nr)) + } else if let Some(tok) = self.index_token() { + Some(FieldKind::Index(tok)) + } else { + None + } + } +} + +pub struct SlicePatComponents { + pub prefix: Vec<ast::Pat>, + pub slice: Option<ast::Pat>, + pub suffix: Vec<ast::Pat>, +} + +impl ast::SlicePat { + pub fn components(&self) -> SlicePatComponents { + let mut args = self.pats().peekable(); + let prefix = args + .peeking_take_while(|p| match p { + ast::Pat::RestPat(_) => false, + ast::Pat::IdentPat(bp) => match bp.pat() { + Some(ast::Pat::RestPat(_)) => false, + _ => true, + }, + ast::Pat::RefPat(rp) => match rp.pat() { + Some(ast::Pat::RestPat(_)) => false, + Some(ast::Pat::IdentPat(bp)) => match bp.pat() { + Some(ast::Pat::RestPat(_)) => false, + _ => true, + }, + _ => true, + }, + _ => true, + }) + .collect(); + let slice = args.next(); + let suffix = args.collect(); + + SlicePatComponents { prefix, slice, suffix } + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum SelfParamKind { + /// self + Owned, + /// &self + Ref, + /// &mut self + MutRef, +} + +impl ast::SelfParam { + pub fn kind(&self) -> SelfParamKind { + if self.amp_token().is_some() { + if self.mut_token().is_some() { + SelfParamKind::MutRef + } else { + SelfParamKind::Ref + } + } else { + SelfParamKind::Owned + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum TypeBoundKind { + /// Trait + PathType(ast::PathType), + /// for<'a> ... + ForType(ast::ForType), + /// 'a + Lifetime(SyntaxToken), +} + +impl ast::TypeBound { + pub fn kind(&self) -> TypeBoundKind { + if let Some(path_type) = support::children(self.syntax()).next() { + TypeBoundKind::PathType(path_type) + } else if let Some(for_type) = support::children(self.syntax()).next() { + TypeBoundKind::ForType(for_type) + } else if let Some(lifetime) = self.lifetime_token() { + TypeBoundKind::Lifetime(lifetime) + } else { + unreachable!() + } + } +} + +pub enum VisibilityKind { + In(ast::Path), + PubCrate, + PubSuper, + PubSelf, + Pub, +} + +impl ast::Visibility { + pub fn kind(&self) -> VisibilityKind { + if let Some(path) = support::children(self.syntax()).next() { + VisibilityKind::In(path) + } else if self.crate_token().is_some() { + VisibilityKind::PubCrate + } else if self.super_token().is_some() { + VisibilityKind::PubSuper + } else if self.self_token().is_some() { + VisibilityKind::PubSelf + } else { + VisibilityKind::Pub + } + } +} + +impl ast::MacroCall { + pub fn is_macro_rules(&self) -> Option<ast::Name> { + let name_ref = self.path()?.segment()?.name_ref()?; + if name_ref.text() == "macro_rules" { + self.name() + } else { + None + } + } + + pub fn is_bang(&self) -> bool { + self.is_macro_rules().is_none() + } +} + +impl ast::LifetimeParam { + pub fn lifetime_bounds(&self) -> impl Iterator<Item = SyntaxToken> { + self.syntax() + .children_with_tokens() + .filter_map(|it| it.into_token()) + .skip_while(|x| x.kind() != T![:]) + .filter(|it| it.kind() == T![lifetime]) + } +} + +impl ast::RangePat { + pub fn start(&self) -> Option<ast::Pat> { + self.syntax() + .children_with_tokens() + .take_while(|it| !(it.kind() == T![..] || it.kind() == T![..=])) + .filter_map(|it| it.into_node()) + .find_map(ast::Pat::cast) + } + + pub fn end(&self) -> Option<ast::Pat> { + self.syntax() + .children_with_tokens() + .skip_while(|it| !(it.kind() == T![..] || it.kind() == T![..=])) + .filter_map(|it| it.into_node()) + .find_map(ast::Pat::cast) + } +} + +impl ast::TokenTree { + pub fn left_delimiter_token(&self) -> Option<SyntaxToken> { + self.syntax() + .first_child_or_token()? + .into_token() + .filter(|it| matches!(it.kind(), T!['{'] | T!['('] | T!['['])) + } + + pub fn right_delimiter_token(&self) -> Option<SyntaxToken> { + self.syntax() + .last_child_or_token()? + .into_token() + .filter(|it| matches!(it.kind(), T!['}'] | T![')'] | T![']'])) + } +} + +impl ast::GenericParamList { + pub fn lifetime_params(&self) -> impl Iterator<Item = ast::LifetimeParam> { + self.generic_params().filter_map(|param| match param { + ast::GenericParam::LifetimeParam(it) => Some(it), + ast::GenericParam::TypeParam(_) | ast::GenericParam::ConstParam(_) => None, + }) + } + pub fn type_params(&self) -> impl Iterator<Item = ast::TypeParam> { + self.generic_params().filter_map(|param| match param { + ast::GenericParam::TypeParam(it) => Some(it), + ast::GenericParam::LifetimeParam(_) | ast::GenericParam::ConstParam(_) => None, + }) + } + pub fn const_params(&self) -> impl Iterator<Item = ast::ConstParam> { + self.generic_params().filter_map(|param| match param { + ast::GenericParam::ConstParam(it) => Some(it), + ast::GenericParam::TypeParam(_) | ast::GenericParam::LifetimeParam(_) => None, + }) + } +} + +impl ast::DocCommentsOwner for ast::SourceFile {} +impl ast::DocCommentsOwner for ast::Fn {} +impl ast::DocCommentsOwner for ast::Struct {} +impl ast::DocCommentsOwner for ast::Union {} +impl ast::DocCommentsOwner for ast::RecordField {} +impl ast::DocCommentsOwner for ast::TupleField {} +impl ast::DocCommentsOwner for ast::Enum {} +impl ast::DocCommentsOwner for ast::Variant {} +impl ast::DocCommentsOwner for ast::Trait {} +impl ast::DocCommentsOwner for ast::Module {} +impl ast::DocCommentsOwner for ast::Static {} +impl ast::DocCommentsOwner for ast::Const {} +impl ast::DocCommentsOwner for ast::TypeAlias {} +impl ast::DocCommentsOwner for ast::Impl {} +impl ast::DocCommentsOwner for ast::MacroCall {} diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs new file mode 100644 index 00000000000..c5ef92733d8 --- /dev/null +++ b/crates/syntax/src/ast/token_ext.rs @@ -0,0 +1,538 @@ +//! There are many AstNodes, but only a few tokens, so we hand-write them here. + +use std::{ + borrow::Cow, + convert::{TryFrom, TryInto}, +}; + +use rustc_lexer::unescape::{unescape_literal, Mode}; + +use crate::{ + ast::{AstToken, Comment, RawString, String, Whitespace}, + TextRange, TextSize, +}; + +impl Comment { + pub fn kind(&self) -> CommentKind { + kind_by_prefix(self.text()) + } + + pub fn prefix(&self) -> &'static str { + for (prefix, k) in COMMENT_PREFIX_TO_KIND.iter() { + if *k == self.kind() && self.text().starts_with(prefix) { + return prefix; + } + } + unreachable!() + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct CommentKind { + pub shape: CommentShape, + pub doc: Option<CommentPlacement>, +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum CommentShape { + Line, + Block, +} + +impl CommentShape { + pub fn is_line(self) -> bool { + self == CommentShape::Line + } + + pub fn is_block(self) -> bool { + self == CommentShape::Block + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum CommentPlacement { + Inner, + Outer, +} + +const COMMENT_PREFIX_TO_KIND: &[(&str, CommentKind)] = { + use {CommentPlacement::*, CommentShape::*}; + &[ + ("////", CommentKind { shape: Line, doc: None }), + ("///", CommentKind { shape: Line, doc: Some(Outer) }), + ("//!", CommentKind { shape: Line, doc: Some(Inner) }), + ("/**", CommentKind { shape: Block, doc: Some(Outer) }), + ("/*!", CommentKind { shape: Block, doc: Some(Inner) }), + ("//", CommentKind { shape: Line, doc: None }), + ("/*", CommentKind { shape: Block, doc: None }), + ] +}; + +fn kind_by_prefix(text: &str) -> CommentKind { + if text == "/**/" { + return CommentKind { shape: CommentShape::Block, doc: None }; + } + for (prefix, kind) in COMMENT_PREFIX_TO_KIND.iter() { + if text.starts_with(prefix) { + return *kind; + } + } + panic!("bad comment text: {:?}", text) +} + +impl Whitespace { + pub fn spans_multiple_lines(&self) -> bool { + let text = self.text(); + text.find('\n').map_or(false, |idx| text[idx + 1..].contains('\n')) + } +} + +pub struct QuoteOffsets { + pub quotes: (TextRange, TextRange), + pub contents: TextRange, +} + +impl QuoteOffsets { + fn new(literal: &str) -> Option<QuoteOffsets> { + let left_quote = literal.find('"')?; + let right_quote = literal.rfind('"')?; + if left_quote == right_quote { + // `literal` only contains one quote + return None; + } + + let start = TextSize::from(0); + let left_quote = TextSize::try_from(left_quote).unwrap() + TextSize::of('"'); + let right_quote = TextSize::try_from(right_quote).unwrap(); + let end = TextSize::of(literal); + + let res = QuoteOffsets { + quotes: (TextRange::new(start, left_quote), TextRange::new(right_quote, end)), + contents: TextRange::new(left_quote, right_quote), + }; + Some(res) + } +} + +pub trait HasQuotes: AstToken { + fn quote_offsets(&self) -> Option<QuoteOffsets> { + let text = self.text().as_str(); + let offsets = QuoteOffsets::new(text)?; + let o = self.syntax().text_range().start(); + let offsets = QuoteOffsets { + quotes: (offsets.quotes.0 + o, offsets.quotes.1 + o), + contents: offsets.contents + o, + }; + Some(offsets) + } + fn open_quote_text_range(&self) -> Option<TextRange> { + self.quote_offsets().map(|it| it.quotes.0) + } + + fn close_quote_text_range(&self) -> Option<TextRange> { + self.quote_offsets().map(|it| it.quotes.1) + } + + fn text_range_between_quotes(&self) -> Option<TextRange> { + self.quote_offsets().map(|it| it.contents) + } +} + +impl HasQuotes for String {} +impl HasQuotes for RawString {} + +pub trait HasStringValue: HasQuotes { + fn value(&self) -> Option<Cow<'_, str>>; +} + +impl HasStringValue for String { + fn value(&self) -> Option<Cow<'_, str>> { + let text = self.text().as_str(); + let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; + + let mut buf = std::string::String::with_capacity(text.len()); + let mut has_error = false; + unescape_literal(text, Mode::Str, &mut |_, unescaped_char| match unescaped_char { + Ok(c) => buf.push(c), + Err(_) => has_error = true, + }); + + if has_error { + return None; + } + // FIXME: don't actually allocate for borrowed case + let res = if buf == text { Cow::Borrowed(text) } else { Cow::Owned(buf) }; + Some(res) + } +} + +impl HasStringValue for RawString { + fn value(&self) -> Option<Cow<'_, str>> { + let text = self.text().as_str(); + let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; + Some(Cow::Borrowed(text)) + } +} + +impl RawString { + pub fn map_range_up(&self, range: TextRange) -> Option<TextRange> { + let contents_range = self.text_range_between_quotes()?; + assert!(TextRange::up_to(contents_range.len()).contains_range(range)); + Some(range + contents_range.start()) + } +} + +#[derive(Debug)] +pub enum FormatSpecifier { + Open, + Close, + Integer, + Identifier, + Colon, + Fill, + Align, + Sign, + NumberSign, + Zero, + DollarSign, + Dot, + Asterisk, + QuestionMark, +} + +pub trait HasFormatSpecifier: AstToken { + fn char_ranges( + &self, + ) -> Option<Vec<(TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>>; + + fn lex_format_specifier<F>(&self, mut callback: F) + where + F: FnMut(TextRange, FormatSpecifier), + { + let char_ranges = if let Some(char_ranges) = self.char_ranges() { + char_ranges + } else { + return; + }; + let mut chars = char_ranges.iter().peekable(); + + while let Some((range, first_char)) = chars.next() { + match first_char { + Ok('{') => { + // Format specifier, see syntax at https://doc.rust-lang.org/std/fmt/index.html#syntax + if let Some((_, Ok('{'))) = chars.peek() { + // Escaped format specifier, `{{` + chars.next(); + continue; + } + + callback(*range, FormatSpecifier::Open); + + // check for integer/identifier + match chars + .peek() + .and_then(|next| next.1.as_ref().ok()) + .copied() + .unwrap_or_default() + { + '0'..='9' => { + // integer + read_integer(&mut chars, &mut callback); + } + c if c == '_' || c.is_alphabetic() => { + // identifier + read_identifier(&mut chars, &mut callback); + } + _ => {} + } + + if let Some((_, Ok(':'))) = chars.peek() { + skip_char_and_emit(&mut chars, FormatSpecifier::Colon, &mut callback); + + // check for fill/align + let mut cloned = chars.clone().take(2); + let first = cloned + .next() + .and_then(|next| next.1.as_ref().ok()) + .copied() + .unwrap_or_default(); + let second = cloned + .next() + .and_then(|next| next.1.as_ref().ok()) + .copied() + .unwrap_or_default(); + match second { + '<' | '^' | '>' => { + // alignment specifier, first char specifies fillment + skip_char_and_emit( + &mut chars, + FormatSpecifier::Fill, + &mut callback, + ); + skip_char_and_emit( + &mut chars, + FormatSpecifier::Align, + &mut callback, + ); + } + _ => match first { + '<' | '^' | '>' => { + skip_char_and_emit( + &mut chars, + FormatSpecifier::Align, + &mut callback, + ); + } + _ => {} + }, + } + + // check for sign + match chars + .peek() + .and_then(|next| next.1.as_ref().ok()) + .copied() + .unwrap_or_default() + { + '+' | '-' => { + skip_char_and_emit( + &mut chars, + FormatSpecifier::Sign, + &mut callback, + ); + } + _ => {} + } + + // check for `#` + if let Some((_, Ok('#'))) = chars.peek() { + skip_char_and_emit( + &mut chars, + FormatSpecifier::NumberSign, + &mut callback, + ); + } + + // check for `0` + let mut cloned = chars.clone().take(2); + let first = cloned.next().and_then(|next| next.1.as_ref().ok()).copied(); + let second = cloned.next().and_then(|next| next.1.as_ref().ok()).copied(); + + if first == Some('0') && second != Some('$') { + skip_char_and_emit(&mut chars, FormatSpecifier::Zero, &mut callback); + } + + // width + match chars + .peek() + .and_then(|next| next.1.as_ref().ok()) + .copied() + .unwrap_or_default() + { + '0'..='9' => { + read_integer(&mut chars, &mut callback); + if let Some((_, Ok('$'))) = chars.peek() { + skip_char_and_emit( + &mut chars, + FormatSpecifier::DollarSign, + &mut callback, + ); + } + } + c if c == '_' || c.is_alphabetic() => { + read_identifier(&mut chars, &mut callback); + // can be either width (indicated by dollar sign, or type in which case + // the next sign has to be `}`) + let next = + chars.peek().and_then(|next| next.1.as_ref().ok()).copied(); + match next { + Some('$') => skip_char_and_emit( + &mut chars, + FormatSpecifier::DollarSign, + &mut callback, + ), + Some('}') => { + skip_char_and_emit( + &mut chars, + FormatSpecifier::Close, + &mut callback, + ); + continue; + } + _ => continue, + }; + } + _ => {} + } + + // precision + if let Some((_, Ok('.'))) = chars.peek() { + skip_char_and_emit(&mut chars, FormatSpecifier::Dot, &mut callback); + + match chars + .peek() + .and_then(|next| next.1.as_ref().ok()) + .copied() + .unwrap_or_default() + { + '*' => { + skip_char_and_emit( + &mut chars, + FormatSpecifier::Asterisk, + &mut callback, + ); + } + '0'..='9' => { + read_integer(&mut chars, &mut callback); + if let Some((_, Ok('$'))) = chars.peek() { + skip_char_and_emit( + &mut chars, + FormatSpecifier::DollarSign, + &mut callback, + ); + } + } + c if c == '_' || c.is_alphabetic() => { + read_identifier(&mut chars, &mut callback); + if chars.peek().and_then(|next| next.1.as_ref().ok()).copied() + != Some('$') + { + continue; + } + skip_char_and_emit( + &mut chars, + FormatSpecifier::DollarSign, + &mut callback, + ); + } + _ => { + continue; + } + } + } + + // type + match chars + .peek() + .and_then(|next| next.1.as_ref().ok()) + .copied() + .unwrap_or_default() + { + '?' => { + skip_char_and_emit( + &mut chars, + FormatSpecifier::QuestionMark, + &mut callback, + ); + } + c if c == '_' || c.is_alphabetic() => { + read_identifier(&mut chars, &mut callback); + } + _ => {} + } + } + + if let Some((_, Ok('}'))) = chars.peek() { + skip_char_and_emit(&mut chars, FormatSpecifier::Close, &mut callback); + } else { + continue; + } + } + _ => { + while let Some((_, Ok(next_char))) = chars.peek() { + match next_char { + '{' => break, + _ => {} + } + chars.next(); + } + } + }; + } + + fn skip_char_and_emit<'a, I, F>( + chars: &mut std::iter::Peekable<I>, + emit: FormatSpecifier, + callback: &mut F, + ) where + I: Iterator<Item = &'a (TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>, + F: FnMut(TextRange, FormatSpecifier), + { + let (range, _) = chars.next().unwrap(); + callback(*range, emit); + } + + fn read_integer<'a, I, F>(chars: &mut std::iter::Peekable<I>, callback: &mut F) + where + I: Iterator<Item = &'a (TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>, + F: FnMut(TextRange, FormatSpecifier), + { + let (mut range, c) = chars.next().unwrap(); + assert!(c.as_ref().unwrap().is_ascii_digit()); + while let Some((r, Ok(next_char))) = chars.peek() { + if next_char.is_ascii_digit() { + chars.next(); + range = range.cover(*r); + } else { + break; + } + } + callback(range, FormatSpecifier::Integer); + } + + fn read_identifier<'a, I, F>(chars: &mut std::iter::Peekable<I>, callback: &mut F) + where + I: Iterator<Item = &'a (TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>, + F: FnMut(TextRange, FormatSpecifier), + { + let (mut range, c) = chars.next().unwrap(); + assert!(c.as_ref().unwrap().is_alphabetic() || *c.as_ref().unwrap() == '_'); + while let Some((r, Ok(next_char))) = chars.peek() { + if *next_char == '_' || next_char.is_ascii_digit() || next_char.is_alphabetic() { + chars.next(); + range = range.cover(*r); + } else { + break; + } + } + callback(range, FormatSpecifier::Identifier); + } + } +} + +impl HasFormatSpecifier for String { + fn char_ranges( + &self, + ) -> Option<Vec<(TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>> { + let text = self.text().as_str(); + let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; + let offset = self.text_range_between_quotes()?.start() - self.syntax().text_range().start(); + + let mut res = Vec::with_capacity(text.len()); + unescape_literal(text, Mode::Str, &mut |range, unescaped_char| { + res.push(( + TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap()) + + offset, + unescaped_char, + )) + }); + + Some(res) + } +} + +impl HasFormatSpecifier for RawString { + fn char_ranges( + &self, + ) -> Option<Vec<(TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>> { + let text = self.text().as_str(); + let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; + let offset = self.text_range_between_quotes()?.start() - self.syntax().text_range().start(); + + let mut res = Vec::with_capacity(text.len()); + for (idx, c) in text.char_indices() { + res.push((TextRange::at(idx.try_into().unwrap(), TextSize::of(c)) + offset, Ok(c))); + } + Some(res) + } +} diff --git a/crates/syntax/src/ast/traits.rs b/crates/syntax/src/ast/traits.rs new file mode 100644 index 00000000000..0bdc22d953f --- /dev/null +++ b/crates/syntax/src/ast/traits.rs @@ -0,0 +1,141 @@ +//! Various traits that are implemented by ast nodes. +//! +//! The implementations are usually trivial, and live in generated.rs +use itertools::Itertools; + +use crate::{ + ast::{self, support, AstChildren, AstNode, AstToken}, + syntax_node::SyntaxElementChildren, + SyntaxToken, T, +}; + +pub trait NameOwner: AstNode { + fn name(&self) -> Option<ast::Name> { + support::child(self.syntax()) + } +} + +pub trait VisibilityOwner: AstNode { + fn visibility(&self) -> Option<ast::Visibility> { + support::child(self.syntax()) + } +} + +pub trait LoopBodyOwner: AstNode { + fn loop_body(&self) -> Option<ast::BlockExpr> { + support::child(self.syntax()) + } + + fn label(&self) -> Option<ast::Label> { + support::child(self.syntax()) + } +} + +pub trait ArgListOwner: AstNode { + fn arg_list(&self) -> Option<ast::ArgList> { + support::child(self.syntax()) + } +} + +pub trait ModuleItemOwner: AstNode { + fn items(&self) -> AstChildren<ast::Item> { + support::children(self.syntax()) + } +} + +pub trait GenericParamsOwner: AstNode { + fn generic_param_list(&self) -> Option<ast::GenericParamList> { + support::child(self.syntax()) + } + + fn where_clause(&self) -> Option<ast::WhereClause> { + support::child(self.syntax()) + } +} + +pub trait TypeBoundsOwner: AstNode { + fn type_bound_list(&self) -> Option<ast::TypeBoundList> { + support::child(self.syntax()) + } + + fn colon_token(&self) -> Option<SyntaxToken> { + support::token(self.syntax(), T![:]) + } +} + +pub trait AttrsOwner: AstNode { + fn attrs(&self) -> AstChildren<ast::Attr> { + support::children(self.syntax()) + } + fn has_atom_attr(&self, atom: &str) -> bool { + self.attrs().filter_map(|x| x.as_simple_atom()).any(|x| x == atom) + } +} + +pub trait DocCommentsOwner: AstNode { + fn doc_comments(&self) -> CommentIter { + CommentIter { iter: self.syntax().children_with_tokens() } + } + + fn doc_comment_text(&self) -> Option<String> { + self.doc_comments().doc_comment_text() + } +} + +impl CommentIter { + pub fn from_syntax_node(syntax_node: &ast::SyntaxNode) -> CommentIter { + CommentIter { iter: syntax_node.children_with_tokens() } + } + + /// Returns the textual content of a doc comment block as a single string. + /// That is, strips leading `///` (+ optional 1 character of whitespace), + /// trailing `*/`, trailing whitespace and then joins the lines. + pub fn doc_comment_text(self) -> Option<String> { + let mut has_comments = false; + let docs = self + .filter(|comment| comment.kind().doc.is_some()) + .map(|comment| { + has_comments = true; + let prefix_len = comment.prefix().len(); + + let line: &str = comment.text().as_str(); + + // Determine if the prefix or prefix + 1 char is stripped + let pos = + if let Some(ws) = line.chars().nth(prefix_len).filter(|c| c.is_whitespace()) { + prefix_len + ws.len_utf8() + } else { + prefix_len + }; + + let end = if comment.kind().shape.is_block() && line.ends_with("*/") { + line.len() - 2 + } else { + line.len() + }; + + // Note that we do not trim the end of the line here + // since whitespace can have special meaning at the end + // of a line in markdown. + line[pos..end].to_owned() + }) + .join("\n"); + + if has_comments { + Some(docs) + } else { + None + } + } +} + +pub struct CommentIter { + iter: SyntaxElementChildren, +} + +impl Iterator for CommentIter { + type Item = ast::Comment; + fn next(&mut self) -> Option<ast::Comment> { + self.iter.by_ref().find_map(|el| el.into_token().and_then(ast::Comment::cast)) + } +} |
