Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 396b56f

Browse files
committed
internal: Add some expr constructors to SyntaxFactory
1 parent cd80380 commit 396b56f

File tree

2 files changed

+175
-2
lines changed

2 files changed

+175
-2
lines changed

src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
FormatArgsArg, FormatArgsExpr, MacroDef, Static, TokenTree,
1111
},
1212
AstToken,
13-
SyntaxKind::*,
13+
SyntaxKind::{self, *},
1414
SyntaxNode, SyntaxToken, T,
1515
};
1616

@@ -50,6 +50,27 @@ impl From<ast::IfExpr> for ElseBranch {
5050
}
5151
}
5252

53+
impl AstNode for ElseBranch {
54+
fn can_cast(kind: SyntaxKind) -> bool {
55+
ast::BlockExpr::can_cast(kind) || ast::IfExpr::can_cast(kind)
56+
}
57+
58+
fn cast(syntax: SyntaxNode) -> Option<Self> {
59+
if let Some(block_expr) = ast::BlockExpr::cast(syntax.clone()) {
60+
Some(Self::Block(block_expr))
61+
} else {
62+
ast::IfExpr::cast(syntax).map(Self::IfExpr)
63+
}
64+
}
65+
66+
fn syntax(&self) -> &SyntaxNode {
67+
match self {
68+
ElseBranch::Block(block_expr) => block_expr.syntax(),
69+
ElseBranch::IfExpr(if_expr) => if_expr.syntax(),
70+
}
71+
}
72+
}
73+
5374
impl ast::IfExpr {
5475
pub fn condition(&self) -> Option<ast::Expr> {
5576
// If the condition is a BlockExpr, check if the then body is missing.

src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,19 @@ impl SyntaxFactory {
167167
ast::BlockExpr { syntax: make::expr_empty_block().syntax().clone_for_update() }
168168
}
169169

170+
pub fn expr_tuple(&self, fields: impl IntoIterator<Item = ast::Expr>) -> ast::TupleExpr {
171+
let (fields, input) = iterator_input(fields);
172+
let ast = make::expr_tuple(fields).clone_for_update();
173+
174+
if let Some(mut mapping) = self.mappings() {
175+
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
176+
builder.map_children(input.into_iter(), ast.fields().map(|it| it.syntax().clone()));
177+
builder.finish(&mut mapping);
178+
}
179+
180+
ast
181+
}
182+
170183
pub fn expr_bin(&self, lhs: ast::Expr, op: ast::BinaryOp, rhs: ast::Expr) -> ast::BinExpr {
171184
let ast::Expr::BinExpr(ast) =
172185
make::expr_bin_op(lhs.clone(), op, rhs.clone()).clone_for_update()
@@ -184,6 +197,10 @@ impl SyntaxFactory {
184197
ast
185198
}
186199

200+
pub fn expr_literal(&self, text: &str) -> ast::Literal {
201+
make::expr_literal(text).clone_for_update()
202+
}
203+
187204
pub fn expr_path(&self, path: ast::Path) -> ast::Expr {
188205
let ast::Expr::PathExpr(ast) = make::expr_path(path.clone()).clone_for_update() else {
189206
unreachable!()
@@ -198,6 +215,18 @@ impl SyntaxFactory {
198215
ast.into()
199216
}
200217

218+
pub fn expr_prefix(&self, op: SyntaxKind, expr: ast::Expr) -> ast::PrefixExpr {
219+
let ast = make::expr_prefix(op, expr.clone()).clone_for_update();
220+
221+
if let Some(mut mapping) = self.mappings() {
222+
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
223+
builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
224+
builder.finish(&mut mapping);
225+
}
226+
227+
ast
228+
}
229+
201230
pub fn expr_ref(&self, expr: ast::Expr, exclusive: bool) -> ast::Expr {
202231
let ast::Expr::RefExpr(ast) = make::expr_ref(expr.clone(), exclusive).clone_for_update()
203232
else {
@@ -229,6 +258,125 @@ impl SyntaxFactory {
229258
ast
230259
}
231260

261+
pub fn expr_if(
262+
&self,
263+
condition: ast::Expr,
264+
then_branch: ast::BlockExpr,
265+
else_branch: Option<ast::ElseBranch>,
266+
) -> ast::IfExpr {
267+
let ast = make::expr_if(condition.clone(), then_branch.clone(), else_branch.clone())
268+
.clone_for_update();
269+
270+
if let Some(mut mapping) = self.mappings() {
271+
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
272+
builder.map_node(condition.syntax().clone(), ast.condition().unwrap().syntax().clone());
273+
builder.map_node(
274+
then_branch.syntax().clone(),
275+
ast.then_branch().unwrap().syntax().clone(),
276+
);
277+
278+
if let Some(else_branch) = else_branch {
279+
builder.map_node(
280+
else_branch.syntax().clone(),
281+
ast.else_branch().unwrap().syntax().clone(),
282+
);
283+
}
284+
builder.finish(&mut mapping);
285+
}
286+
287+
ast
288+
}
289+
290+
pub fn expr_let(&self, pattern: ast::Pat, expr: ast::Expr) -> ast::LetExpr {
291+
let ast = make::expr_let(pattern.clone(), expr.clone()).clone_for_update();
292+
293+
if let Some(mut mapping) = self.mappings() {
294+
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
295+
builder.map_node(pattern.syntax().clone(), ast.pat().unwrap().syntax().clone());
296+
builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
297+
builder.finish(&mut mapping);
298+
}
299+
300+
ast
301+
}
302+
303+
pub fn expr_stmt(&self, expr: ast::Expr) -> ast::ExprStmt {
304+
let ast = make::expr_stmt(expr.clone()).clone_for_update();
305+
306+
if let Some(mut mapping) = self.mappings() {
307+
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
308+
builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
309+
builder.finish(&mut mapping);
310+
}
311+
312+
ast
313+
}
314+
315+
pub fn expr_match(&self, expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::MatchExpr {
316+
let ast = make::expr_match(expr.clone(), match_arm_list.clone()).clone_for_update();
317+
318+
if let Some(mut mapping) = self.mappings() {
319+
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
320+
builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
321+
builder.map_node(
322+
match_arm_list.syntax().clone(),
323+
ast.match_arm_list().unwrap().syntax().clone(),
324+
);
325+
builder.finish(&mut mapping);
326+
}
327+
328+
ast
329+
}
330+
331+
pub fn match_arm(
332+
&self,
333+
pat: ast::Pat,
334+
guard: Option<ast::MatchGuard>,
335+
expr: ast::Expr,
336+
) -> ast::MatchArm {
337+
let ast = make::match_arm(pat.clone(), guard.clone(), expr.clone()).clone_for_update();
338+
339+
if let Some(mut mapping) = self.mappings() {
340+
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
341+
builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone());
342+
if let Some(guard) = guard {
343+
builder.map_node(guard.syntax().clone(), ast.guard().unwrap().syntax().clone());
344+
}
345+
builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
346+
builder.finish(&mut mapping);
347+
}
348+
349+
ast
350+
}
351+
352+
pub fn match_guard(&self, condition: ast::Expr) -> ast::MatchGuard {
353+
let ast = make::match_guard(condition.clone()).clone_for_update();
354+
355+
if let Some(mut mapping) = self.mappings() {
356+
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
357+
builder.map_node(condition.syntax().clone(), ast.condition().unwrap().syntax().clone());
358+
builder.finish(&mut mapping);
359+
}
360+
361+
ast
362+
}
363+
364+
pub fn match_arm_list(
365+
&self,
366+
match_arms: impl IntoIterator<Item = ast::MatchArm>,
367+
) -> ast::MatchArmList {
368+
let (match_arms, input) = iterator_input(match_arms);
369+
let ast = make::match_arm_list(match_arms).clone_for_update();
370+
371+
if let Some(mut mapping) = self.mappings() {
372+
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
373+
builder.map_children(input.into_iter(), ast.arms().map(|it| it.syntax().clone()));
374+
builder.finish(&mut mapping);
375+
}
376+
377+
ast
378+
}
379+
232380
pub fn let_stmt(
233381
&self,
234382
pattern: ast::Pat,
@@ -572,13 +720,17 @@ impl SyntaxFactory {
572720
make::token(kind)
573721
}
574722

575-
pub fn whitespace(&self, text: &str) -> ast::SyntaxToken {
723+
pub fn whitespace(&self, text: &str) -> SyntaxToken {
576724
make::tokens::whitespace(text)
577725
}
578726
}
579727

580728
// `ext` constructors
581729
impl SyntaxFactory {
730+
pub fn expr_unit(&self) -> ast::Expr {
731+
self.expr_tuple([]).into()
732+
}
733+
582734
pub fn ident_path(&self, ident: &str) -> ast::Path {
583735
self.path_unqualified(self.path_segment(self.name_ref(ident)))
584736
}

0 commit comments

Comments
 (0)