Skip to main content

rustidy_ast/
expr.rs

1//! Expression
2
3// Modules
4pub mod with_block;
5pub mod without_block;
6
7// Exports
8pub use self::{
9	with_block::{BlockExpression, ExpressionWithBlock, MatchExpression, Scrutinee},
10	without_block::{
11		ArrayExpression,
12		AwaitExpression,
13		CallExpression,
14		ClosureExpression,
15		ContinueExpression,
16		ExpressionWithoutBlock,
17		FieldExpression,
18		GroupedExpression,
19		IndexExpression,
20		MacroInvocation,
21		MethodCallExpression,
22		OperatorExpression,
23		PathExpression,
24		ReturnExpression,
25		StructExpression,
26		TupleExpression,
27		TupleIndexingExpression,
28	},
29};
30
31// Imports
32use {
33	crate::attr::OuterAttrOrDocComment,
34	rustidy_ast_literal::{IntegerLiteral, LiteralExpression, StringLiteral},
35	rustidy_format::{Format, Formattable},
36	rustidy_parse::{
37		FromRecursiveRoot,
38		Parse,
39		ParseRecursive,
40		Parser,
41		ParserError,
42		RecursiveWrapper,
43	},
44	rustidy_print::Print,
45	rustidy_util::{ArenaData, ArenaIdx},
46};
47
48/// `Expression`
49#[derive(PartialEq, Eq, Clone, Debug)]
50#[derive(serde::Serialize, serde::Deserialize)]
51#[derive(Parse, Formattable, Format, Print)]
52pub struct Expression(pub ArenaIdx<ExpressionInner>);
53
54impl Expression {
55	/// Gets a literal out of this expression, if it is one.
56	#[must_use]
57	pub fn as_literal(&self) -> Option<&LiteralExpression> {
58		self.0
59			.try_as_without_block_ref()?.0
60			.inner
61			.try_as_literal_ref()
62	}
63
64	/// Gets a string literal out of this expression, if it is one.
65	#[must_use]
66	pub fn as_string_literal(&self) -> Option<&StringLiteral> {
67		self.as_literal()?.try_as_string_ref()
68	}
69
70	/// Gets an integer literal out of this expression, if it is one.
71	#[must_use]
72	pub fn as_integer_literal(&self) -> Option<&IntegerLiteral> {
73		self.as_literal()?.try_as_integer_ref()
74	}
75}
76
77impl FromRecursiveRoot<ExpressionInner> for Expression {
78	fn from_recursive_root(expr: ExpressionInner, _parser: &mut Parser) -> Self {
79		let idx = ArenaIdx::new(expr);
80		Self(idx)
81	}
82}
83
84#[derive(PartialEq, Eq, Clone, Debug)]
85#[derive(ArenaData)]
86#[derive(derive_more::From, derive_more::TryInto)]
87#[derive(strum::EnumTryAs)]
88#[derive(serde::Serialize, serde::Deserialize)]
89#[derive(ParseRecursive, Formattable, Format, Print)]
90#[parse_recursive(root = ExpressionInner)]
91pub enum ExpressionInner {
92	#[parse_recursive(recursive)]
93	WithoutBlock(ExpressionWithoutBlock),
94	WithBlock(ExpressionWithBlock),
95}
96
97// TODO: Once we implement precedence and bubble all the attributes
98//       to the top automatically, derive this impl
99impl Parse for ExpressionInner {
100	type Error = ExpressionInnerError;
101
102	fn parse_from(parser: &mut Parser) -> Result<Self, Self::Error> {
103		let attrs = parser.parse::<Vec<OuterAttrOrDocComment>>()?;
104		let RecursiveWrapper(mut expr, _) = parser.parse::<RecursiveWrapper<Self, Self>>()?;
105
106		match &mut expr {
107			Self::WithoutBlock(expr) => expr.0.attrs.extend(attrs),
108			Self::WithBlock(expr) => expr.0.attrs.extend(attrs),
109		}
110
111		Ok(expr)
112	}
113}
114
115#[derive(derive_more::Debug, derive_more::From, rustidy_parse::ParseError)]
116pub enum ExpressionInnerError {
117	#[parse_error(transparent)]
118	Attributes(ParserError<Vec<OuterAttrOrDocComment>>),
119
120	#[parse_error(transparent)]
121	Inner(ParserError<RecursiveWrapper<ExpressionInner, ExpressionInner>>),
122}