aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2021-05-09 17:51:06 +0100
committerAleksey Kladov <[email protected]>2021-05-09 17:55:43 +0100
commit4f3c0adc5aafea465c71c85f36484da970df1ba2 (patch)
tree4cb502a6c345c3ecfb4090067ab1de2cfd69ed55 /crates
parent680a0d54e4d2d474ae41f4f4a95c749495a02883 (diff)
internal: introduce `ast::make::ext` module with common shortcuts
There's a tension between keeping a well-architectured minimal orthogonal set of constructs, and providing convenience functions. Relieve this pressure by introducing an dedicated module for non-orthogonal shortcuts. This is inspired by the django.shortcuts module which serves a similar purpose architecturally.
Diffstat (limited to 'crates')
-rw-r--r--crates/ide_assists/src/handlers/early_return.rs4
-rw-r--r--crates/ide_assists/src/handlers/expand_glob_import.rs3
-rw-r--r--crates/ide_assists/src/handlers/extract_function.rs62
-rw-r--r--crates/ide_assists/src/handlers/generate_function.rs2
-rw-r--r--crates/ide_assists/src/handlers/move_bounds.rs6
-rw-r--r--crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs8
-rw-r--r--crates/ide_assists/src/handlers/replace_let_with_if_let.rs2
-rw-r--r--crates/ide_assists/src/handlers/replace_unwrap_with_match.rs21
-rw-r--r--crates/ide_assists/src/handlers/wrap_return_type_in_result.rs4
-rw-r--r--crates/ide_assists/src/tests/generated.rs2
-rw-r--r--crates/ide_assists/src/utils.rs4
-rw-r--r--crates/ide_db/src/helpers/merge_imports.rs2
-rw-r--r--crates/ide_db/src/ty_filter.rs6
-rw-r--r--crates/syntax/src/ast/make.rs95
14 files changed, 104 insertions, 117 deletions
diff --git a/crates/ide_assists/src/handlers/early_return.rs b/crates/ide_assists/src/handlers/early_return.rs
index c66f8c05d..5eb6a57f0 100644
--- a/crates/ide_assists/src/handlers/early_return.rs
+++ b/crates/ide_assists/src/handlers/early_return.rs
@@ -130,9 +130,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
130 once(make::ident_pat(make::name("it")).into()), 130 once(make::ident_pat(make::name("it")).into()),
131 ); 131 );
132 let expr = { 132 let expr = {
133 let name_ref = make::name_ref("it"); 133 let path = make::ext::ident_path("it");
134 let segment = make::path_segment(name_ref);
135 let path = make::path_unqualified(segment);
136 make::expr_path(path) 134 make::expr_path(path)
137 }; 135 };
138 make::match_arm(once(pat.into()), expr) 136 make::match_arm(once(pat.into()), expr)
diff --git a/crates/ide_assists/src/handlers/expand_glob_import.rs b/crates/ide_assists/src/handlers/expand_glob_import.rs
index e3095f26b..da8d245e5 100644
--- a/crates/ide_assists/src/handlers/expand_glob_import.rs
+++ b/crates/ide_assists/src/handlers/expand_glob_import.rs
@@ -65,8 +65,7 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti
65 65
66 let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs); 66 let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs);
67 let expanded = make::use_tree_list(names_to_import.iter().map(|n| { 67 let expanded = make::use_tree_list(names_to_import.iter().map(|n| {
68 let path = 68 let path = make::ext::ident_path(&n.to_string());
69 make::path_unqualified(make::path_segment(make::name_ref(&n.to_string())));
70 make::use_tree(path, None, None, false) 69 make::use_tree(path, None, None, false)
71 })) 70 }))
72 .clone_for_update(); 71 .clone_for_update();
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs
index 494ef4621..6311afc1f 100644
--- a/crates/ide_assists/src/handlers/extract_function.rs
+++ b/crates/ide_assists/src/handlers/extract_function.rs
@@ -956,10 +956,10 @@ fn format_replacement(ctx: &AssistContext, fun: &Function, indent: IndentLevel)
956 let args = fun.params.iter().map(|param| param.to_arg(ctx)); 956 let args = fun.params.iter().map(|param| param.to_arg(ctx));
957 let args = make::arg_list(args); 957 let args = make::arg_list(args);
958 let call_expr = if fun.self_param.is_some() { 958 let call_expr = if fun.self_param.is_some() {
959 let self_arg = make::expr_path(make_path_from_text("self")); 959 let self_arg = make::expr_path(make::ext::ident_path("self"));
960 make::expr_method_call(self_arg, &fun.name, args) 960 make::expr_method_call(self_arg, &fun.name, args)
961 } else { 961 } else {
962 let func = make::expr_path(make_path_from_text(&fun.name)); 962 let func = make::expr_path(make::ext::ident_path(&fun.name));
963 make::expr_call(func, args) 963 make::expr_call(func, args)
964 }; 964 };
965 965
@@ -1054,11 +1054,11 @@ impl FlowHandler {
1054 make::expr_if(condition, block, None) 1054 make::expr_if(condition, block, None)
1055 } 1055 }
1056 FlowHandler::IfOption { action } => { 1056 FlowHandler::IfOption { action } => {
1057 let path = make_path_from_text("Some"); 1057 let path = make::ext::ident_path("Some");
1058 let value_pat = make::ident_pat(make::name("value")); 1058 let value_pat = make::ident_pat(make::name("value"));
1059 let pattern = make::tuple_struct_pat(path, iter::once(value_pat.into())); 1059 let pattern = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1060 let cond = make::condition(call_expr, Some(pattern.into())); 1060 let cond = make::condition(call_expr, Some(pattern.into()));
1061 let value = make::expr_path(make_path_from_text("value")); 1061 let value = make::expr_path(make::ext::ident_path("value"));
1062 let action_expr = action.make_result_handler(Some(value)); 1062 let action_expr = action.make_result_handler(Some(value));
1063 let action_stmt = make::expr_stmt(action_expr); 1063 let action_stmt = make::expr_stmt(action_expr);
1064 let then = make::block_expr(iter::once(action_stmt.into()), None); 1064 let then = make::block_expr(iter::once(action_stmt.into()), None);
@@ -1068,14 +1068,14 @@ impl FlowHandler {
1068 let some_name = "value"; 1068 let some_name = "value";
1069 1069
1070 let some_arm = { 1070 let some_arm = {
1071 let path = make_path_from_text("Some"); 1071 let path = make::ext::ident_path("Some");
1072 let value_pat = make::ident_pat(make::name(some_name)); 1072 let value_pat = make::ident_pat(make::name(some_name));
1073 let pat = make::tuple_struct_pat(path, iter::once(value_pat.into())); 1073 let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1074 let value = make::expr_path(make_path_from_text(some_name)); 1074 let value = make::expr_path(make::ext::ident_path(some_name));
1075 make::match_arm(iter::once(pat.into()), value) 1075 make::match_arm(iter::once(pat.into()), value)
1076 }; 1076 };
1077 let none_arm = { 1077 let none_arm = {
1078 let path = make_path_from_text("None"); 1078 let path = make::ext::ident_path("None");
1079 let pat = make::path_pat(path); 1079 let pat = make::path_pat(path);
1080 make::match_arm(iter::once(pat), none.make_result_handler(None)) 1080 make::match_arm(iter::once(pat), none.make_result_handler(None))
1081 }; 1081 };
@@ -1087,17 +1087,17 @@ impl FlowHandler {
1087 let err_name = "value"; 1087 let err_name = "value";
1088 1088
1089 let ok_arm = { 1089 let ok_arm = {
1090 let path = make_path_from_text("Ok"); 1090 let path = make::ext::ident_path("Ok");
1091 let value_pat = make::ident_pat(make::name(ok_name)); 1091 let value_pat = make::ident_pat(make::name(ok_name));
1092 let pat = make::tuple_struct_pat(path, iter::once(value_pat.into())); 1092 let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1093 let value = make::expr_path(make_path_from_text(ok_name)); 1093 let value = make::expr_path(make::ext::ident_path(ok_name));
1094 make::match_arm(iter::once(pat.into()), value) 1094 make::match_arm(iter::once(pat.into()), value)
1095 }; 1095 };
1096 let err_arm = { 1096 let err_arm = {
1097 let path = make_path_from_text("Err"); 1097 let path = make::ext::ident_path("Err");
1098 let value_pat = make::ident_pat(make::name(err_name)); 1098 let value_pat = make::ident_pat(make::name(err_name));
1099 let pat = make::tuple_struct_pat(path, iter::once(value_pat.into())); 1099 let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1100 let value = make::expr_path(make_path_from_text(err_name)); 1100 let value = make::expr_path(make::ext::ident_path(err_name));
1101 make::match_arm(iter::once(pat.into()), err.make_result_handler(Some(value))) 1101 make::match_arm(iter::once(pat.into()), err.make_result_handler(Some(value)))
1102 }; 1102 };
1103 let arms = make::match_arm_list(vec![ok_arm, err_arm]); 1103 let arms = make::match_arm_list(vec![ok_arm, err_arm]);
@@ -1107,13 +1107,9 @@ impl FlowHandler {
1107 } 1107 }
1108} 1108}
1109 1109
1110fn make_path_from_text(text: &str) -> ast::Path {
1111 make::path_unqualified(make::path_segment(make::name_ref(text)))
1112}
1113
1114fn path_expr_from_local(ctx: &AssistContext, var: Local) -> ast::Expr { 1110fn path_expr_from_local(ctx: &AssistContext, var: Local) -> ast::Expr {
1115 let name = var.name(ctx.db()).unwrap().to_string(); 1111 let name = var.name(ctx.db()).unwrap().to_string();
1116 make::expr_path(make_path_from_text(&name)) 1112 make::expr_path(make::ext::ident_path(&name))
1117} 1113}
1118 1114
1119fn format_function( 1115fn format_function(
@@ -1179,7 +1175,7 @@ fn make_ret_ty(ctx: &AssistContext, module: hir::Module, fun: &Function) -> Opti
1179 fun_ty.make_ty(ctx, module) 1175 fun_ty.make_ty(ctx, module)
1180 } 1176 }
1181 FlowHandler::Try { kind: TryKind::Option } => { 1177 FlowHandler::Try { kind: TryKind::Option } => {
1182 make::ty_generic(make::name_ref("Option"), iter::once(fun_ty.make_ty(ctx, module))) 1178 make::ext::ty_option(fun_ty.make_ty(ctx, module))
1183 } 1179 }
1184 FlowHandler::Try { kind: TryKind::Result { ty: parent_ret_ty } } => { 1180 FlowHandler::Try { kind: TryKind::Result { ty: parent_ret_ty } } => {
1185 let handler_ty = parent_ret_ty 1181 let handler_ty = parent_ret_ty
@@ -1187,29 +1183,21 @@ fn make_ret_ty(ctx: &AssistContext, module: hir::Module, fun: &Function) -> Opti
1187 .nth(1) 1183 .nth(1)
1188 .map(|ty| make_ty(&ty, ctx, module)) 1184 .map(|ty| make_ty(&ty, ctx, module))
1189 .unwrap_or_else(make::ty_unit); 1185 .unwrap_or_else(make::ty_unit);
1190 make::ty_generic( 1186 make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
1191 make::name_ref("Result"),
1192 vec![fun_ty.make_ty(ctx, module), handler_ty],
1193 )
1194 } 1187 }
1195 FlowHandler::If { .. } => make::ty_bool(), 1188 FlowHandler::If { .. } => make::ext::ty_bool(),
1196 FlowHandler::IfOption { action } => { 1189 FlowHandler::IfOption { action } => {
1197 let handler_ty = action 1190 let handler_ty = action
1198 .expr_ty(ctx) 1191 .expr_ty(ctx)
1199 .map(|ty| make_ty(&ty, ctx, module)) 1192 .map(|ty| make_ty(&ty, ctx, module))
1200 .unwrap_or_else(make::ty_unit); 1193 .unwrap_or_else(make::ty_unit);
1201 make::ty_generic(make::name_ref("Option"), iter::once(handler_ty)) 1194 make::ext::ty_option(handler_ty)
1202 }
1203 FlowHandler::MatchOption { .. } => {
1204 make::ty_generic(make::name_ref("Option"), iter::once(fun_ty.make_ty(ctx, module)))
1205 } 1195 }
1196 FlowHandler::MatchOption { .. } => make::ext::ty_option(fun_ty.make_ty(ctx, module)),
1206 FlowHandler::MatchResult { err } => { 1197 FlowHandler::MatchResult { err } => {
1207 let handler_ty = 1198 let handler_ty =
1208 err.expr_ty(ctx).map(|ty| make_ty(&ty, ctx, module)).unwrap_or_else(make::ty_unit); 1199 err.expr_ty(ctx).map(|ty| make_ty(&ty, ctx, module)).unwrap_or_else(make::ty_unit);
1209 make::ty_generic( 1200 make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
1210 make::name_ref("Result"),
1211 vec![fun_ty.make_ty(ctx, module), handler_ty],
1212 )
1213 } 1201 }
1214 }; 1202 };
1215 Some(make::ret_type(ret_ty)) 1203 Some(make::ret_type(ret_ty))
@@ -1296,7 +1284,7 @@ fn make_body(
1296 TryKind::Option => "Some", 1284 TryKind::Option => "Some",
1297 TryKind::Result { .. } => "Ok", 1285 TryKind::Result { .. } => "Ok",
1298 }; 1286 };
1299 let func = make::expr_path(make_path_from_text(constructor)); 1287 let func = make::expr_path(make::ext::ident_path(constructor));
1300 let args = make::arg_list(iter::once(tail_expr)); 1288 let args = make::arg_list(iter::once(tail_expr));
1301 make::expr_call(func, args) 1289 make::expr_call(func, args)
1302 }) 1290 })
@@ -1306,16 +1294,16 @@ fn make_body(
1306 with_tail_expr(block, lit_false.into()) 1294 with_tail_expr(block, lit_false.into())
1307 } 1295 }
1308 FlowHandler::IfOption { .. } => { 1296 FlowHandler::IfOption { .. } => {
1309 let none = make::expr_path(make_path_from_text("None")); 1297 let none = make::expr_path(make::ext::ident_path("None"));
1310 with_tail_expr(block, none) 1298 with_tail_expr(block, none)
1311 } 1299 }
1312 FlowHandler::MatchOption { .. } => map_tail_expr(block, |tail_expr| { 1300 FlowHandler::MatchOption { .. } => map_tail_expr(block, |tail_expr| {
1313 let some = make::expr_path(make_path_from_text("Some")); 1301 let some = make::expr_path(make::ext::ident_path("Some"));
1314 let args = make::arg_list(iter::once(tail_expr)); 1302 let args = make::arg_list(iter::once(tail_expr));
1315 make::expr_call(some, args) 1303 make::expr_call(some, args)
1316 }), 1304 }),
1317 FlowHandler::MatchResult { .. } => map_tail_expr(block, |tail_expr| { 1305 FlowHandler::MatchResult { .. } => map_tail_expr(block, |tail_expr| {
1318 let ok = make::expr_path(make_path_from_text("Ok")); 1306 let ok = make::expr_path(make::ext::ident_path("Ok"));
1319 let args = make::arg_list(iter::once(tail_expr)); 1307 let args = make::arg_list(iter::once(tail_expr));
1320 make::expr_call(ok, args) 1308 make::expr_call(ok, args)
1321 }), 1309 }),
@@ -1483,13 +1471,13 @@ fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option<ast::Expr>) -> Op
1483 FlowHandler::IfOption { .. } => { 1471 FlowHandler::IfOption { .. } => {
1484 let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new())); 1472 let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
1485 let args = make::arg_list(iter::once(expr)); 1473 let args = make::arg_list(iter::once(expr));
1486 make::expr_call(make::expr_path(make_path_from_text("Some")), args) 1474 make::expr_call(make::expr_path(make::ext::ident_path("Some")), args)
1487 } 1475 }
1488 FlowHandler::MatchOption { .. } => make::expr_path(make_path_from_text("None")), 1476 FlowHandler::MatchOption { .. } => make::expr_path(make::ext::ident_path("None")),
1489 FlowHandler::MatchResult { .. } => { 1477 FlowHandler::MatchResult { .. } => {
1490 let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new())); 1478 let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
1491 let args = make::arg_list(iter::once(expr)); 1479 let args = make::arg_list(iter::once(expr));
1492 make::expr_call(make::expr_path(make_path_from_text("Err")), args) 1480 make::expr_call(make::expr_path(make::ext::ident_path("Err")), args)
1493 } 1481 }
1494 }; 1482 };
1495 Some(make::expr_return(Some(value)).clone_for_update()) 1483 Some(make::expr_return(Some(value)).clone_for_update())
diff --git a/crates/ide_assists/src/handlers/generate_function.rs b/crates/ide_assists/src/handlers/generate_function.rs
index 6f95b1a07..bc9fc524b 100644
--- a/crates/ide_assists/src/handlers/generate_function.rs
+++ b/crates/ide_assists/src/handlers/generate_function.rs
@@ -175,7 +175,7 @@ impl FunctionBuilder {
175 } 175 }
176 176
177 fn render(self) -> FunctionTemplate { 177 fn render(self) -> FunctionTemplate {
178 let placeholder_expr = make::expr_todo(); 178 let placeholder_expr = make::ext::expr_todo();
179 let fn_body = make::block_expr(vec![], Some(placeholder_expr)); 179 let fn_body = make::block_expr(vec![], Some(placeholder_expr));
180 let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None }; 180 let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None };
181 let mut fn_def = make::fn_( 181 let mut fn_def = make::fn_(
diff --git a/crates/ide_assists/src/handlers/move_bounds.rs b/crates/ide_assists/src/handlers/move_bounds.rs
index 011a28d44..fa3f76609 100644
--- a/crates/ide_assists/src/handlers/move_bounds.rs
+++ b/crates/ide_assists/src/handlers/move_bounds.rs
@@ -63,11 +63,7 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext
63} 63}
64 64
65fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> { 65fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> {
66 let path = { 66 let path = make::ext::ident_path(&param.name()?.syntax().to_string());
67 let name_ref = make::name_ref(&param.name()?.syntax().to_string());
68 let segment = make::path_segment(name_ref);
69 make::path_unqualified(segment)
70 };
71 let predicate = make::where_pred(path, param.type_bound_list()?.bounds()); 67 let predicate = make::where_pred(path, param.type_bound_list()?.bounds());
72 Some(predicate.clone_for_update()) 68 Some(predicate.clone_for_update())
73} 69}
diff --git a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
index 694d897d1..10d9cec31 100644
--- a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -84,7 +84,7 @@ pub(crate) fn replace_derive_with_manual_impl(
84 add_assist(acc, ctx, &attr, &args, &trait_path, Some(trait_), &adt)?; 84 add_assist(acc, ctx, &attr, &args, &trait_path, Some(trait_), &adt)?;
85 } 85 }
86 if no_traits_found { 86 if no_traits_found {
87 let trait_path = make::path_unqualified(make::path_segment(make::name_ref(trait_name))); 87 let trait_path = make::ext::ident_path(trait_name);
88 add_assist(acc, ctx, &attr, &args, &trait_path, None, &adt)?; 88 add_assist(acc, ctx, &attr, &args, &trait_path, None, &adt)?;
89 } 89 }
90 Some(()) 90 Some(())
@@ -159,10 +159,8 @@ fn impl_def_from_trait(
159 if trait_items.is_empty() { 159 if trait_items.is_empty() {
160 return None; 160 return None;
161 } 161 }
162 let impl_def = make::impl_trait( 162 let impl_def =
163 trait_path.clone(), 163 make::impl_trait(trait_path.clone(), make::ext::ident_path(&annotated_name.text()));
164 make::path_unqualified(make::path_segment(make::name_ref(&annotated_name.text()))),
165 );
166 let (impl_def, first_assoc_item) = 164 let (impl_def, first_assoc_item) =
167 add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope); 165 add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope);
168 Some((impl_def, first_assoc_item)) 166 Some((impl_def, first_assoc_item))
diff --git a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
index be7e724b5..f811234c0 100644
--- a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
+++ b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
@@ -53,7 +53,7 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) ->
53 let with_placeholder: ast::Pat = match happy_variant { 53 let with_placeholder: ast::Pat = match happy_variant {
54 None => make::wildcard_pat().into(), 54 None => make::wildcard_pat().into(),
55 Some(var_name) => make::tuple_struct_pat( 55 Some(var_name) => make::tuple_struct_pat(
56 make::path_unqualified(make::path_segment(make::name_ref(var_name))), 56 make::ext::ident_path(var_name),
57 once(make::wildcard_pat().into()), 57 once(make::wildcard_pat().into()),
58 ) 58 )
59 .into(), 59 .into(),
diff --git a/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs
index a986a6ae8..0fec961b4 100644
--- a/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs
+++ b/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs
@@ -32,7 +32,7 @@ use ide_db::ty_filter::TryEnum;
32// fn main() { 32// fn main() {
33// let x: Result<i32, i32> = Result::Ok(92); 33// let x: Result<i32, i32> = Result::Ok(92);
34// let y = match x { 34// let y = match x {
35// Ok(a) => a, 35// Ok(it) => it,
36// $0_ => unreachable!(), 36// $0_ => unreachable!(),
37// }; 37// };
38// } 38// }
@@ -52,16 +52,17 @@ pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext)
52 "Replace unwrap with match", 52 "Replace unwrap with match",
53 target, 53 target,
54 |builder| { 54 |builder| {
55 let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant))); 55 let ok_path = make::ext::ident_path(happy_variant);
56 let it = make::ident_pat(make::name("a")).into(); 56 let it = make::ident_pat(make::name("it")).into();
57 let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); 57 let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into();
58 58
59 let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); 59 let bind_path = make::ext::ident_path("it");
60 let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path)); 60 let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path));
61 61
62 let unreachable_call = make::expr_unreachable(); 62 let err_arm = make::match_arm(
63 let err_arm = 63 iter::once(make::wildcard_pat().into()),
64 make::match_arm(iter::once(make::wildcard_pat().into()), unreachable_call); 64 make::ext::expr_unreachable(),
65 );
65 66
66 let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); 67 let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]);
67 let match_expr = make::expr_match(caller.clone(), match_arm_list) 68 let match_expr = make::expr_match(caller.clone(), match_arm_list)
@@ -110,7 +111,7 @@ fn i<T>(a: T) -> T { a }
110fn main() { 111fn main() {
111 let x: Result<i32, i32> = Result::Ok(92); 112 let x: Result<i32, i32> = Result::Ok(92);
112 let y = match i(x) { 113 let y = match i(x) {
113 Ok(a) => a, 114 Ok(it) => it,
114 $0_ => unreachable!(), 115 $0_ => unreachable!(),
115 }; 116 };
116} 117}
@@ -136,7 +137,7 @@ fn i<T>(a: T) -> T { a }
136fn main() { 137fn main() {
137 let x = Option::Some(92); 138 let x = Option::Some(92);
138 let y = match i(x) { 139 let y = match i(x) {
139 Some(a) => a, 140 Some(it) => it,
140 $0_ => unreachable!(), 141 $0_ => unreachable!(),
141 }; 142 };
142} 143}
@@ -162,7 +163,7 @@ fn i<T>(a: T) -> T { a }
162fn main() { 163fn main() {
163 let x: Result<i32, i32> = Result::Ok(92); 164 let x: Result<i32, i32> = Result::Ok(92);
164 let y = match i(x) { 165 let y = match i(x) {
165 Ok(a) => a, 166 Ok(it) => it,
166 $0_ => unreachable!(), 167 $0_ => unreachable!(),
167 }.count_zeroes(); 168 }.count_zeroes();
168} 169}
diff --git a/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs b/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs
index e838630ea..2f1da82c7 100644
--- a/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs
+++ b/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs
@@ -54,9 +54,7 @@ pub(crate) fn wrap_return_type_in_result(acc: &mut Assists, ctx: &AssistContext)
54 54
55 for ret_expr_arg in tail_return_expr_collector.exprs_to_wrap { 55 for ret_expr_arg in tail_return_expr_collector.exprs_to_wrap {
56 let ok_wrapped = make::expr_call( 56 let ok_wrapped = make::expr_call(
57 make::expr_path(make::path_unqualified(make::path_segment(make::name_ref( 57 make::expr_path(make::ext::ident_path("Ok")),
58 "Ok",
59 )))),
60 make::arg_list(iter::once(ret_expr_arg.clone())), 58 make::arg_list(iter::once(ret_expr_arg.clone())),
61 ); 59 );
62 builder.replace_ast(ret_expr_arg, ok_wrapped); 60 builder.replace_ast(ret_expr_arg, ok_wrapped);
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index 59bcef8fb..49c1a9776 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -1531,7 +1531,7 @@ enum Result<T, E> { Ok(T), Err(E) }
1531fn main() { 1531fn main() {
1532 let x: Result<i32, i32> = Result::Ok(92); 1532 let x: Result<i32, i32> = Result::Ok(92);
1533 let y = match x { 1533 let y = match x {
1534 Ok(a) => a, 1534 Ok(it) => it,
1535 $0_ => unreachable!(), 1535 $0_ => unreachable!(),
1536 }; 1536 };
1537} 1537}
diff --git a/crates/ide_assists/src/utils.rs b/crates/ide_assists/src/utils.rs
index 5a90ad715..0dcf20c61 100644
--- a/crates/ide_assists/src/utils.rs
+++ b/crates/ide_assists/src/utils.rs
@@ -159,8 +159,8 @@ pub fn add_trait_assoc_items_to_impl(
159 match fn_def.body() { 159 match fn_def.body() {
160 Some(_) => fn_def, 160 Some(_) => fn_def,
161 None => { 161 None => {
162 let body = 162 let body = make::block_expr(None, Some(make::ext::expr_todo()))
163 make::block_expr(None, Some(make::expr_todo())).indent(edit::IndentLevel(1)); 163 .indent(edit::IndentLevel(1));
164 fn_def.with_body(body) 164 fn_def.with_body(body)
165 } 165 }
166 } 166 }
diff --git a/crates/ide_db/src/helpers/merge_imports.rs b/crates/ide_db/src/helpers/merge_imports.rs
index 3f5bbef7f..148297279 100644
--- a/crates/ide_db/src/helpers/merge_imports.rs
+++ b/crates/ide_db/src/helpers/merge_imports.rs
@@ -137,7 +137,7 @@ fn recursive_merge(
137 None, 137 None,
138 false, 138 false,
139 ); 139 );
140 use_trees.insert(idx, make::glob_use_tree()); 140 use_trees.insert(idx, make::use_tree_glob());
141 continue; 141 continue;
142 } 142 }
143 143
diff --git a/crates/ide_db/src/ty_filter.rs b/crates/ide_db/src/ty_filter.rs
index 988ecd060..00678bf3e 100644
--- a/crates/ide_db/src/ty_filter.rs
+++ b/crates/ide_db/src/ty_filter.rs
@@ -43,7 +43,7 @@ impl TryEnum {
43 pub fn sad_pattern(self) -> ast::Pat { 43 pub fn sad_pattern(self) -> ast::Pat {
44 match self { 44 match self {
45 TryEnum::Result => make::tuple_struct_pat( 45 TryEnum::Result => make::tuple_struct_pat(
46 make::path_unqualified(make::path_segment(make::name_ref("Err"))), 46 make::ext::ident_path("Err"),
47 iter::once(make::wildcard_pat().into()), 47 iter::once(make::wildcard_pat().into()),
48 ) 48 )
49 .into(), 49 .into(),
@@ -54,12 +54,12 @@ impl TryEnum {
54 pub fn happy_pattern(self) -> ast::Pat { 54 pub fn happy_pattern(self) -> ast::Pat {
55 match self { 55 match self {
56 TryEnum::Result => make::tuple_struct_pat( 56 TryEnum::Result => make::tuple_struct_pat(
57 make::path_unqualified(make::path_segment(make::name_ref("Ok"))), 57 make::ext::ident_path("Ok"),
58 iter::once(make::wildcard_pat().into()), 58 iter::once(make::wildcard_pat().into()),
59 ) 59 )
60 .into(), 60 .into(),
61 TryEnum::Option => make::tuple_struct_pat( 61 TryEnum::Option => make::tuple_struct_pat(
62 make::path_unqualified(make::path_segment(make::name_ref("Some"))), 62 make::ext::ident_path("Some"),
63 iter::once(make::wildcard_pat().into()), 63 iter::once(make::wildcard_pat().into()),
64 ) 64 )
65 .into(), 65 .into(),
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index c39e248ce..a378b1d37 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -3,7 +3,7 @@
3//! 3//!
4//! Note that all functions here intended to be stupid constructors, which just 4//! Note that all functions here intended to be stupid constructors, which just
5//! assemble a finish node from immediate children. If you want to do something 5//! assemble a finish node from immediate children. If you want to do something
6//! smarter than that, it probably doesn't belong in this module. 6//! smarter than that, it belongs to the `ext` submodule.
7//! 7//!
8//! Keep in mind that `from_text` functions should be kept private. The public 8//! Keep in mind that `from_text` functions should be kept private. The public
9//! API should require to assemble every node piecewise. The trick of 9//! API should require to assemble every node piecewise. The trick of
@@ -14,13 +14,49 @@ use stdx::{format_to, never};
14 14
15use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken}; 15use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken};
16 16
17/// While the parent module defines basic atomic "constructors", the `ext`
18/// module defines shortcuts for common things.
19///
20/// It's named `ext` rather than `shortcuts` just to keep it short.
21pub mod ext {
22 use super::*;
23
24 pub fn ident_path(ident: &str) -> ast::Path {
25 path_unqualified(path_segment(name_ref(ident)))
26 }
27
28 pub fn expr_unreachable() -> ast::Expr {
29 expr_from_text("unreachable!()")
30 }
31 pub fn expr_todo() -> ast::Expr {
32 expr_from_text("todo!()")
33 }
34
35 pub fn ty_bool() -> ast::Type {
36 ty_path(ident_path("bool"))
37 }
38 pub fn ty_option(t: ast::Type) -> ast::Type {
39 ty_from_text(&format!("Option<{}>", t))
40 }
41 pub fn ty_result(t: ast::Type, e: ast::Type) -> ast::Type {
42 ty_from_text(&format!("Result<{}, {}>", t, e))
43 }
44}
45
17pub fn name(text: &str) -> ast::Name { 46pub fn name(text: &str) -> ast::Name {
18 ast_from_text(&format!("mod {}{};", raw_ident_esc(text), text)) 47 ast_from_text(&format!("mod {}{};", raw_ident_esc(text), text))
19} 48}
20
21pub fn name_ref(text: &str) -> ast::NameRef { 49pub fn name_ref(text: &str) -> ast::NameRef {
22 ast_from_text(&format!("fn f() {{ {}{}; }}", raw_ident_esc(text), text)) 50 ast_from_text(&format!("fn f() {{ {}{}; }}", raw_ident_esc(text), text))
23} 51}
52fn raw_ident_esc(ident: &str) -> &'static str {
53 let is_keyword = parser::SyntaxKind::from_keyword(ident).is_some();
54 if is_keyword && !matches!(ident, "self" | "crate" | "super" | "Self") {
55 "r#"
56 } else {
57 ""
58 }
59}
24 60
25pub fn lifetime(text: &str) -> ast::Lifetime { 61pub fn lifetime(text: &str) -> ast::Lifetime {
26 let mut text = text; 62 let mut text = text;
@@ -32,15 +68,6 @@ pub fn lifetime(text: &str) -> ast::Lifetime {
32 ast_from_text(&format!("fn f<{}>() {{ }}", text)) 68 ast_from_text(&format!("fn f<{}>() {{ }}", text))
33} 69}
34 70
35fn raw_ident_esc(ident: &str) -> &'static str {
36 let is_keyword = parser::SyntaxKind::from_keyword(ident).is_some();
37 if is_keyword && !matches!(ident, "self" | "crate" | "super" | "Self") {
38 "r#"
39 } else {
40 ""
41 }
42}
43
44// FIXME: replace stringly-typed constructor with a family of typed ctors, a-la 71// FIXME: replace stringly-typed constructor with a family of typed ctors, a-la
45// `expr_xxx`. 72// `expr_xxx`.
46pub fn ty(text: &str) -> ast::Type { 73pub fn ty(text: &str) -> ast::Type {
@@ -49,9 +76,6 @@ pub fn ty(text: &str) -> ast::Type {
49pub fn ty_unit() -> ast::Type { 76pub fn ty_unit() -> ast::Type {
50 ty_from_text("()") 77 ty_from_text("()")
51} 78}
52pub fn ty_bool() -> ast::Type {
53 ty_path(path_unqualified(path_segment(name_ref("bool"))))
54}
55pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type { 79pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type {
56 let mut count: usize = 0; 80 let mut count: usize = 0;
57 let mut contents = types.into_iter().inspect(|_| count += 1).join(", "); 81 let mut contents = types.into_iter().inspect(|_| count += 1).join(", ");
@@ -61,11 +85,6 @@ pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type {
61 85
62 ty_from_text(&format!("({})", contents)) 86 ty_from_text(&format!("({})", contents))
63} 87}
64// FIXME: handle path to type
65pub fn ty_generic(name: ast::NameRef, types: impl IntoIterator<Item = ast::Type>) -> ast::Type {
66 let contents = types.into_iter().join(", ");
67 ty_from_text(&format!("{}<{}>", name, contents))
68}
69pub fn ty_ref(target: ast::Type, exclusive: bool) -> ast::Type { 88pub fn ty_ref(target: ast::Type, exclusive: bool) -> ast::Type {
70 ty_from_text(&if exclusive { format!("&mut {}", target) } else { format!("&{}", target) }) 89 ty_from_text(&if exclusive { format!("&mut {}", target) } else { format!("&{}", target) })
71} 90}
@@ -107,7 +126,7 @@ pub fn path_unqualified(segment: ast::PathSegment) -> ast::Path {
107pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path { 126pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path {
108 ast_from_text(&format!("{}::{}", qual, segment)) 127 ast_from_text(&format!("{}::{}", qual, segment))
109} 128}
110 129// FIXME: path concatenation operation doesn't make sense as AST op.
111pub fn path_concat(first: ast::Path, second: ast::Path) -> ast::Path { 130pub fn path_concat(first: ast::Path, second: ast::Path) -> ast::Path {
112 ast_from_text(&format!("{}::{}", first, second)) 131 ast_from_text(&format!("{}::{}", first, second))
113} 132}
@@ -123,15 +142,14 @@ pub fn path_from_segments(
123 format!("use {};", segments) 142 format!("use {};", segments)
124 }) 143 })
125} 144}
126 145// FIXME: should not be pub
127pub fn path_from_text(text: &str) -> ast::Path { 146pub fn path_from_text(text: &str) -> ast::Path {
128 ast_from_text(&format!("fn main() {{ let test = {}; }}", text)) 147 ast_from_text(&format!("fn main() {{ let test = {}; }}", text))
129} 148}
130 149
131pub fn glob_use_tree() -> ast::UseTree { 150pub fn use_tree_glob() -> ast::UseTree {
132 ast_from_text("use *;") 151 ast_from_text("use *;")
133} 152}
134
135pub fn use_tree( 153pub fn use_tree(
136 path: ast::Path, 154 path: ast::Path,
137 use_tree_list: Option<ast::UseTreeList>, 155 use_tree_list: Option<ast::UseTreeList>,
@@ -226,15 +244,6 @@ pub fn expr_literal(text: &str) -> ast::Literal {
226pub fn expr_empty_block() -> ast::Expr { 244pub fn expr_empty_block() -> ast::Expr {
227 expr_from_text("{}") 245 expr_from_text("{}")
228} 246}
229pub fn expr_unimplemented() -> ast::Expr {
230 expr_from_text("unimplemented!()")
231}
232pub fn expr_unreachable() -> ast::Expr {
233 expr_from_text("unreachable!()")
234}
235pub fn expr_todo() -> ast::Expr {
236 expr_from_text("todo!()")
237}
238pub fn expr_path(path: ast::Path) -> ast::Expr { 247pub fn expr_path(path: ast::Path) -> ast::Expr {
239 expr_from_text(&path.to_string()) 248 expr_from_text(&path.to_string())
240} 249}
@@ -463,17 +472,6 @@ pub fn expr_stmt(expr: ast::Expr) -> ast::ExprStmt {
463 ast_from_text(&format!("fn f() {{ {}{} (); }}", expr, semi)) 472 ast_from_text(&format!("fn f() {{ {}{} (); }}", expr, semi))
464} 473}
465 474
466pub fn token(kind: SyntaxKind) -> SyntaxToken {
467 tokens::SOURCE_FILE
468 .tree()
469 .syntax()
470 .clone_for_update()
471 .descendants_with_tokens()
472 .filter_map(|it| it.into_token())
473 .find(|it| it.kind() == kind)
474 .unwrap_or_else(|| panic!("unhandled token: {:?}", kind))
475}
476
477pub fn param(pat: ast::Pat, ty: ast::Type) -> ast::Param { 475pub fn param(pat: ast::Pat, ty: ast::Type) -> ast::Param {
478 ast_from_text(&format!("fn f({}: {}) {{ }}", pat, ty)) 476 ast_from_text(&format!("fn f({}: {}) {{ }}", pat, ty))
479} 477}
@@ -611,6 +609,17 @@ fn unroot(n: SyntaxNode) -> SyntaxNode {
611 SyntaxNode::new_root(n.green().into()) 609 SyntaxNode::new_root(n.green().into())
612} 610}
613 611
612pub fn token(kind: SyntaxKind) -> SyntaxToken {
613 tokens::SOURCE_FILE
614 .tree()
615 .syntax()
616 .clone_for_update()
617 .descendants_with_tokens()
618 .filter_map(|it| it.into_token())
619 .find(|it| it.kind() == kind)
620 .unwrap_or_else(|| panic!("unhandled token: {:?}", kind))
621}
622
614pub mod tokens { 623pub mod tokens {
615 use once_cell::sync::Lazy; 624 use once_cell::sync::Lazy;
616 625