Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/syntax/src/ast/syntax_factory/constructors.rs')
-rw-r--r--crates/syntax/src/ast/syntax_factory/constructors.rs364
1 files changed, 359 insertions, 5 deletions
diff --git a/crates/syntax/src/ast/syntax_factory/constructors.rs b/crates/syntax/src/ast/syntax_factory/constructors.rs
index bea6bfeafc..572622db54 100644
--- a/crates/syntax/src/ast/syntax_factory/constructors.rs
+++ b/crates/syntax/src/ast/syntax_factory/constructors.rs
@@ -1,6 +1,9 @@
//! Wrappers over [`make`] constructors
use crate::{
- ast::{self, make, HasGenericParams, HasName, HasTypeBounds, HasVisibility},
+ ast::{
+ self, make, HasArgList, HasGenericArgs, HasGenericParams, HasName, HasTypeBounds,
+ HasVisibility,
+ },
syntax_editor::SyntaxMappingBuilder,
AstNode, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken,
};
@@ -12,6 +15,14 @@ impl SyntaxFactory {
make::name(name).clone_for_update()
}
+ pub fn name_ref(&self, name: &str) -> ast::NameRef {
+ make::name_ref(name).clone_for_update()
+ }
+
+ pub fn lifetime(&self, text: &str) -> ast::Lifetime {
+ make::lifetime(text).clone_for_update()
+ }
+
pub fn ty(&self, text: &str) -> ast::Type {
make::ty(text).clone_for_update()
}
@@ -24,6 +35,20 @@ impl SyntaxFactory {
ast
}
+ pub fn ty_path(&self, path: ast::Path) -> ast::PathType {
+ let ast::Type::PathType(ast) = make::ty_path(path.clone()).clone_for_update() else {
+ unreachable!()
+ };
+
+ if let Some(mut mapping) = self.mappings() {
+ let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+ builder.map_node(path.syntax().clone(), ast.path().unwrap().syntax().clone());
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
pub fn type_param(
&self,
name: ast::Name,
@@ -46,6 +71,71 @@ impl SyntaxFactory {
ast
}
+ pub fn path_segment(&self, name_ref: ast::NameRef) -> ast::PathSegment {
+ let ast = make::path_segment(name_ref.clone()).clone_for_update();
+
+ if let Some(mut mapping) = self.mappings() {
+ let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+ builder.map_node(name_ref.syntax().clone(), ast.name_ref().unwrap().syntax().clone());
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
+ pub fn path_segment_generics(
+ &self,
+ name_ref: ast::NameRef,
+ generic_arg_list: ast::GenericArgList,
+ ) -> ast::PathSegment {
+ let ast::Type::PathType(path) = make::ty(&format!("{name_ref}{generic_arg_list}")) else {
+ unreachable!();
+ };
+
+ let ast = path.path().unwrap().segment().unwrap().clone_for_update();
+
+ if let Some(mut mapping) = self.mappings() {
+ let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+ builder.map_node(name_ref.syntax().clone(), ast.name_ref().unwrap().syntax().clone());
+ builder.map_node(
+ generic_arg_list.syntax().clone(),
+ ast.generic_arg_list().unwrap().syntax().clone(),
+ );
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
+ pub fn path_unqualified(&self, segment: ast::PathSegment) -> ast::Path {
+ let ast = make::path_unqualified(segment.clone()).clone_for_update();
+
+ if let Some(mut mapping) = self.mappings() {
+ let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+ builder.map_node(segment.syntax().clone(), ast.segment().unwrap().syntax().clone());
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
+ pub fn path_from_segments(
+ &self,
+ segments: impl IntoIterator<Item = ast::PathSegment>,
+ is_abs: bool,
+ ) -> ast::Path {
+ let (segments, input) = iterator_input(segments);
+ let ast = make::path_from_segments(segments, is_abs).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.segments().map(|it| it.syntax().clone()));
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
pub fn ident_pat(&self, ref_: bool, mut_: bool, name: ast::Name) -> ast::IdentPat {
let ast = make::ident_pat(ref_, mut_, name.clone()).clone_for_update();
@@ -58,6 +148,32 @@ impl SyntaxFactory {
ast
}
+ pub fn wildcard_pat(&self) -> ast::WildcardPat {
+ make::wildcard_pat().clone_for_update()
+ }
+
+ pub fn literal_pat(&self, text: &str) -> ast::LiteralPat {
+ make::literal_pat(text).clone_for_update()
+ }
+
+ pub fn tuple_struct_pat(
+ &self,
+ path: ast::Path,
+ fields: impl IntoIterator<Item = ast::Pat>,
+ ) -> ast::TupleStructPat {
+ let (fields, input) = iterator_input(fields);
+ let ast = make::tuple_struct_pat(path.clone(), fields).clone_for_update();
+
+ if let Some(mut mapping) = self.mappings() {
+ let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+ builder.map_node(path.syntax().clone(), ast.path().unwrap().syntax().clone());
+ builder.map_children(input.into_iter(), ast.fields().map(|it| it.syntax().clone()));
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
pub fn block_expr(
&self,
statements: impl IntoIterator<Item = ast::Stmt>,
@@ -95,7 +211,20 @@ impl SyntaxFactory {
}
pub fn expr_empty_block(&self) -> ast::BlockExpr {
- ast::BlockExpr { syntax: make::expr_empty_block().syntax().clone_for_update() }
+ make::expr_empty_block().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 {
@@ -115,6 +244,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!()
@@ -129,6 +262,49 @@ 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_call(&self, expr: ast::Expr, arg_list: ast::ArgList) -> ast::CallExpr {
+ // FIXME: `make::expr_call`` should return a `CallExpr`, not just an `Expr`
+ let ast::Expr::CallExpr(ast) =
+ make::expr_call(expr.clone(), arg_list.clone()).clone_for_update()
+ else {
+ unreachable!()
+ };
+
+ 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(arg_list.syntax().clone(), ast.arg_list().unwrap().syntax().clone());
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
+ pub fn arg_list(&self, args: impl IntoIterator<Item = ast::Expr>) -> ast::ArgList {
+ let (args, input) = iterator_input(args);
+ let ast = make::arg_list(args).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.args().map(|it| it.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 {
@@ -160,6 +336,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,
@@ -185,6 +480,30 @@ impl SyntaxFactory {
ast
}
+ pub fn type_arg(&self, ty: ast::Type) -> ast::TypeArg {
+ let ast = make::type_arg(ty.clone()).clone_for_update();
+
+ if let Some(mut mapping) = self.mappings() {
+ let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+ builder.map_node(ty.syntax().clone(), ast.ty().unwrap().syntax().clone());
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
+ pub fn lifetime_arg(&self, lifetime: ast::Lifetime) -> ast::LifetimeArg {
+ let ast = make::lifetime_arg(lifetime.clone()).clone_for_update();
+
+ if let Some(mut mapping) = self.mappings() {
+ let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+ builder.map_node(lifetime.syntax().clone(), ast.lifetime().unwrap().syntax().clone());
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
pub fn item_const(
&self,
visibility: Option<ast::Visibility>,
@@ -252,12 +571,17 @@ impl SyntaxFactory {
ast
}
- pub fn turbofish_generic_arg_list(
+ pub fn generic_arg_list(
&self,
generic_args: impl IntoIterator<Item = ast::GenericArg>,
+ is_turbo: bool,
) -> ast::GenericArgList {
let (generic_args, input) = iterator_input(generic_args);
- let ast = make::turbofish_generic_arg_list(generic_args.clone()).clone_for_update();
+ let ast = if is_turbo {
+ make::turbofish_generic_arg_list(generic_args).clone_for_update()
+ } else {
+ make::generic_arg_list(generic_args).clone_for_update()
+ };
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -503,11 +827,41 @@ 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 ident_path(&self, ident: &str) -> ast::Path {
+ self.path_unqualified(self.path_segment(self.name_ref(ident)))
+ }
+
+ pub fn expr_unit(&self) -> ast::Expr {
+ self.expr_tuple([]).into()
+ }
+
+ pub fn ty_option(&self, t: ast::Type) -> ast::PathType {
+ let generic_arg_list = self.generic_arg_list([self.type_arg(t).into()], false);
+ let path = self.path_unqualified(
+ self.path_segment_generics(self.name_ref("Option"), generic_arg_list),
+ );
+
+ self.ty_path(path)
+ }
+
+ pub fn ty_result(&self, t: ast::Type, e: ast::Type) -> ast::PathType {
+ let generic_arg_list =
+ self.generic_arg_list([self.type_arg(t).into(), self.type_arg(e).into()], false);
+ let path = self.path_unqualified(
+ self.path_segment_generics(self.name_ref("Result"), generic_arg_list),
+ );
+
+ self.ty_path(path)
+ }
+}
+
// We need to collect `input` here instead of taking `impl IntoIterator + Clone`,
// because if we took `impl IntoIterator + Clone`, that could be something like an
// `Iterator::map` with a closure that also makes use of a `SyntaxFactory` constructor.