aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/assists
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/assists')
-rw-r--r--crates/ra_assists/src/assists/fill_match_arms.rs67
1 files changed, 51 insertions, 16 deletions
diff --git a/crates/ra_assists/src/assists/fill_match_arms.rs b/crates/ra_assists/src/assists/fill_match_arms.rs
index b75bd44eb..99d80998c 100644
--- a/crates/ra_assists/src/assists/fill_match_arms.rs
+++ b/crates/ra_assists/src/assists/fill_match_arms.rs
@@ -46,19 +46,24 @@ pub(crate) fn fill_match_arms(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
46 }; 46 };
47 47
48 let expr = match_expr.expr()?; 48 let expr = match_expr.expr()?;
49 let enum_def = { 49 let (enum_def, module) = {
50 let analyzer = ctx.source_analyzer(expr.syntax(), None); 50 let analyzer = ctx.source_analyzer(expr.syntax(), None);
51 resolve_enum_def(ctx.db, &analyzer, &expr)? 51 (resolve_enum_def(ctx.db, &analyzer, &expr)?, analyzer.module()?)
52 }; 52 };
53 let variant_list = enum_def.variant_list()?; 53 let variants = enum_def.variants(ctx.db);
54 if variants.is_empty() {
55 return None;
56 }
57
58 let db = ctx.db;
54 59
55 ctx.add_assist(AssistId("fill_match_arms"), "fill match arms", |edit| { 60 ctx.add_assist(AssistId("fill_match_arms"), "fill match arms", |edit| {
56 let indent_level = IndentLevel::from_node(match_arm_list.syntax()); 61 let indent_level = IndentLevel::from_node(match_arm_list.syntax());
57 62
58 let new_arm_list = { 63 let new_arm_list = {
59 let variants = variant_list.variants();
60 let arms = variants 64 let arms = variants
61 .filter_map(build_pat) 65 .into_iter()
66 .filter_map(|variant| build_pat(db, module, variant))
62 .map(|pat| make::match_arm(iter::once(pat), make::expr_unit())); 67 .map(|pat| make::match_arm(iter::once(pat), make::expr_unit()));
63 indent_level.increase_indent(make::match_arm_list(arms)) 68 indent_level.increase_indent(make::match_arm_list(arms))
64 }; 69 };
@@ -80,23 +85,25 @@ fn resolve_enum_def(
80 db: &impl HirDatabase, 85 db: &impl HirDatabase,
81 analyzer: &hir::SourceAnalyzer, 86 analyzer: &hir::SourceAnalyzer,
82 expr: &ast::Expr, 87 expr: &ast::Expr,
83) -> Option<ast::EnumDef> { 88) -> Option<hir::Enum> {
84 let expr_ty = analyzer.type_of(db, &expr)?; 89 let expr_ty = analyzer.type_of(db, &expr)?;
85 90
86 let res = expr_ty.autoderef(db).find_map(|ty| match ty.as_adt() { 91 let result = expr_ty.autoderef(db).find_map(|ty| match ty.as_adt() {
87 Some(Adt::Enum(e)) => Some(e.source(db).value), 92 Some(Adt::Enum(e)) => Some(e),
88 _ => None, 93 _ => None,
89 }); 94 });
90 res 95 result
91} 96}
92 97
93fn build_pat(var: ast::EnumVariant) -> Option<ast::Pat> { 98fn build_pat(
94 let path = make::path_qualified( 99 db: &impl HirDatabase,
95 make::path_from_name_ref(make::name_ref(&var.parent_enum().name()?.syntax().to_string())), 100 module: hir::Module,
96 make::name_ref(&var.name()?.syntax().to_string()), 101 var: hir::EnumVariant,
97 ); 102) -> Option<ast::Pat> {
103 let path = crate::ast_transform::path_to_ast(module.find_use_path(db, var.into())?);
98 104
99 let pat: ast::Pat = match var.kind() { 105 // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
106 let pat: ast::Pat = match var.source(db).value.kind() {
100 ast::StructKind::Tuple(field_list) => { 107 ast::StructKind::Tuple(field_list) => {
101 let pats = 108 let pats =
102 iter::repeat(make::placeholder_pat().into()).take(field_list.fields().count()); 109 iter::repeat(make::placeholder_pat().into()).take(field_list.fields().count());
@@ -106,7 +113,7 @@ fn build_pat(var: ast::EnumVariant) -> Option<ast::Pat> {
106 let pats = field_list.fields().map(|f| make::bind_pat(f.name().unwrap()).into()); 113 let pats = field_list.fields().map(|f| make::bind_pat(f.name().unwrap()).into());
107 make::record_pat(path, pats).into() 114 make::record_pat(path, pats).into()
108 } 115 }
109 ast::StructKind::Unit => make::path_pat(path).into(), 116 ast::StructKind::Unit => make::path_pat(path),
110 }; 117 };
111 118
112 Some(pat) 119 Some(pat)
@@ -252,4 +259,32 @@ mod tests {
252 "#, 259 "#,
253 ); 260 );
254 } 261 }
262
263 #[test]
264 fn fill_match_arms_qualifies_path() {
265 check_assist(
266 fill_match_arms,
267 r#"
268 mod foo { pub enum E { X, Y } }
269 use foo::E::X;
270
271 fn main() {
272 match X {
273 <|>
274 }
275 }
276 "#,
277 r#"
278 mod foo { pub enum E { X, Y } }
279 use foo::E::X;
280
281 fn main() {
282 match <|>X {
283 X => (),
284 foo::E::Y => (),
285 }
286 }
287 "#,
288 );
289 }
255} 290}