mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-26 03:45:04 +00:00
internal: Add some expr constructors to SyntaxFactory
This commit is contained in:
parent
f5ff966dea
commit
ce2398fee8
2 changed files with 175 additions and 2 deletions
|
@ -10,7 +10,7 @@ use crate::{
|
|||
FormatArgsArg, FormatArgsExpr, MacroDef, Static, TokenTree,
|
||||
},
|
||||
AstToken,
|
||||
SyntaxKind::*,
|
||||
SyntaxKind::{self, *},
|
||||
SyntaxNode, SyntaxToken, T,
|
||||
};
|
||||
|
||||
|
@ -50,6 +50,27 @@ impl From<ast::IfExpr> for ElseBranch {
|
|||
}
|
||||
}
|
||||
|
||||
impl AstNode for ElseBranch {
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
ast::BlockExpr::can_cast(kind) || ast::IfExpr::can_cast(kind)
|
||||
}
|
||||
|
||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||
if let Some(block_expr) = ast::BlockExpr::cast(syntax.clone()) {
|
||||
Some(Self::Block(block_expr))
|
||||
} else {
|
||||
ast::IfExpr::cast(syntax).map(Self::IfExpr)
|
||||
}
|
||||
}
|
||||
|
||||
fn syntax(&self) -> &SyntaxNode {
|
||||
match self {
|
||||
ElseBranch::Block(block_expr) => block_expr.syntax(),
|
||||
ElseBranch::IfExpr(if_expr) => if_expr.syntax(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ast::IfExpr {
|
||||
pub fn condition(&self) -> Option<ast::Expr> {
|
||||
// If the condition is a BlockExpr, check if the then body is missing.
|
||||
|
|
|
@ -167,6 +167,19 @@ impl SyntaxFactory {
|
|||
ast::BlockExpr { syntax: make::expr_empty_block().syntax().clone_for_update() }
|
||||
}
|
||||
|
||||
pub fn expr_tuple(&self, fields: impl IntoIterator<Item = ast::Expr>) -> ast::TupleExpr {
|
||||
let (fields, input) = iterator_input(fields);
|
||||
let ast = make::expr_tuple(fields).clone_for_update();
|
||||
|
||||
if let Some(mut mapping) = self.mappings() {
|
||||
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
|
||||
builder.map_children(input.into_iter(), ast.fields().map(|it| it.syntax().clone()));
|
||||
builder.finish(&mut mapping);
|
||||
}
|
||||
|
||||
ast
|
||||
}
|
||||
|
||||
pub fn expr_bin(&self, lhs: ast::Expr, op: ast::BinaryOp, rhs: ast::Expr) -> ast::BinExpr {
|
||||
let ast::Expr::BinExpr(ast) =
|
||||
make::expr_bin_op(lhs.clone(), op, rhs.clone()).clone_for_update()
|
||||
|
@ -184,6 +197,10 @@ impl SyntaxFactory {
|
|||
ast
|
||||
}
|
||||
|
||||
pub fn expr_literal(&self, text: &str) -> ast::Literal {
|
||||
make::expr_literal(text).clone_for_update()
|
||||
}
|
||||
|
||||
pub fn expr_path(&self, path: ast::Path) -> ast::Expr {
|
||||
let ast::Expr::PathExpr(ast) = make::expr_path(path.clone()).clone_for_update() else {
|
||||
unreachable!()
|
||||
|
@ -198,6 +215,18 @@ impl SyntaxFactory {
|
|||
ast.into()
|
||||
}
|
||||
|
||||
pub fn expr_prefix(&self, op: SyntaxKind, expr: ast::Expr) -> ast::PrefixExpr {
|
||||
let ast = make::expr_prefix(op, expr.clone()).clone_for_update();
|
||||
|
||||
if let Some(mut mapping) = self.mappings() {
|
||||
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
|
||||
builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
|
||||
builder.finish(&mut mapping);
|
||||
}
|
||||
|
||||
ast
|
||||
}
|
||||
|
||||
pub fn expr_ref(&self, expr: ast::Expr, exclusive: bool) -> ast::Expr {
|
||||
let ast::Expr::RefExpr(ast) = make::expr_ref(expr.clone(), exclusive).clone_for_update()
|
||||
else {
|
||||
|
@ -229,6 +258,125 @@ impl SyntaxFactory {
|
|||
ast
|
||||
}
|
||||
|
||||
pub fn expr_if(
|
||||
&self,
|
||||
condition: ast::Expr,
|
||||
then_branch: ast::BlockExpr,
|
||||
else_branch: Option<ast::ElseBranch>,
|
||||
) -> ast::IfExpr {
|
||||
let ast = make::expr_if(condition.clone(), then_branch.clone(), else_branch.clone())
|
||||
.clone_for_update();
|
||||
|
||||
if let Some(mut mapping) = self.mappings() {
|
||||
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
|
||||
builder.map_node(condition.syntax().clone(), ast.condition().unwrap().syntax().clone());
|
||||
builder.map_node(
|
||||
then_branch.syntax().clone(),
|
||||
ast.then_branch().unwrap().syntax().clone(),
|
||||
);
|
||||
|
||||
if let Some(else_branch) = else_branch {
|
||||
builder.map_node(
|
||||
else_branch.syntax().clone(),
|
||||
ast.else_branch().unwrap().syntax().clone(),
|
||||
);
|
||||
}
|
||||
builder.finish(&mut mapping);
|
||||
}
|
||||
|
||||
ast
|
||||
}
|
||||
|
||||
pub fn expr_let(&self, pattern: ast::Pat, expr: ast::Expr) -> ast::LetExpr {
|
||||
let ast = make::expr_let(pattern.clone(), expr.clone()).clone_for_update();
|
||||
|
||||
if let Some(mut mapping) = self.mappings() {
|
||||
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
|
||||
builder.map_node(pattern.syntax().clone(), ast.pat().unwrap().syntax().clone());
|
||||
builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
|
||||
builder.finish(&mut mapping);
|
||||
}
|
||||
|
||||
ast
|
||||
}
|
||||
|
||||
pub fn expr_stmt(&self, expr: ast::Expr) -> ast::ExprStmt {
|
||||
let ast = make::expr_stmt(expr.clone()).clone_for_update();
|
||||
|
||||
if let Some(mut mapping) = self.mappings() {
|
||||
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
|
||||
builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
|
||||
builder.finish(&mut mapping);
|
||||
}
|
||||
|
||||
ast
|
||||
}
|
||||
|
||||
pub fn expr_match(&self, expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::MatchExpr {
|
||||
let ast = make::expr_match(expr.clone(), match_arm_list.clone()).clone_for_update();
|
||||
|
||||
if let Some(mut mapping) = self.mappings() {
|
||||
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
|
||||
builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
|
||||
builder.map_node(
|
||||
match_arm_list.syntax().clone(),
|
||||
ast.match_arm_list().unwrap().syntax().clone(),
|
||||
);
|
||||
builder.finish(&mut mapping);
|
||||
}
|
||||
|
||||
ast
|
||||
}
|
||||
|
||||
pub fn match_arm(
|
||||
&self,
|
||||
pat: ast::Pat,
|
||||
guard: Option<ast::MatchGuard>,
|
||||
expr: ast::Expr,
|
||||
) -> ast::MatchArm {
|
||||
let ast = make::match_arm(pat.clone(), guard.clone(), expr.clone()).clone_for_update();
|
||||
|
||||
if let Some(mut mapping) = self.mappings() {
|
||||
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
|
||||
builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone());
|
||||
if let Some(guard) = guard {
|
||||
builder.map_node(guard.syntax().clone(), ast.guard().unwrap().syntax().clone());
|
||||
}
|
||||
builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
|
||||
builder.finish(&mut mapping);
|
||||
}
|
||||
|
||||
ast
|
||||
}
|
||||
|
||||
pub fn match_guard(&self, condition: ast::Expr) -> ast::MatchGuard {
|
||||
let ast = make::match_guard(condition.clone()).clone_for_update();
|
||||
|
||||
if let Some(mut mapping) = self.mappings() {
|
||||
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
|
||||
builder.map_node(condition.syntax().clone(), ast.condition().unwrap().syntax().clone());
|
||||
builder.finish(&mut mapping);
|
||||
}
|
||||
|
||||
ast
|
||||
}
|
||||
|
||||
pub fn match_arm_list(
|
||||
&self,
|
||||
match_arms: impl IntoIterator<Item = ast::MatchArm>,
|
||||
) -> ast::MatchArmList {
|
||||
let (match_arms, input) = iterator_input(match_arms);
|
||||
let ast = make::match_arm_list(match_arms).clone_for_update();
|
||||
|
||||
if let Some(mut mapping) = self.mappings() {
|
||||
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
|
||||
builder.map_children(input.into_iter(), ast.arms().map(|it| it.syntax().clone()));
|
||||
builder.finish(&mut mapping);
|
||||
}
|
||||
|
||||
ast
|
||||
}
|
||||
|
||||
pub fn let_stmt(
|
||||
&self,
|
||||
pattern: ast::Pat,
|
||||
|
@ -572,13 +720,17 @@ impl SyntaxFactory {
|
|||
make::token(kind)
|
||||
}
|
||||
|
||||
pub fn whitespace(&self, text: &str) -> ast::SyntaxToken {
|
||||
pub fn whitespace(&self, text: &str) -> SyntaxToken {
|
||||
make::tokens::whitespace(text)
|
||||
}
|
||||
}
|
||||
|
||||
// `ext` constructors
|
||||
impl SyntaxFactory {
|
||||
pub fn expr_unit(&self) -> ast::Expr {
|
||||
self.expr_tuple([]).into()
|
||||
}
|
||||
|
||||
pub fn ident_path(&self, ident: &str) -> ast::Path {
|
||||
self.path_unqualified(self.path_segment(self.name_ref(ident)))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue