Skip to content

Commit 21be386

Browse files
Merge #2809
2809: Qualify paths in 'fill match arms' assist r=matklad a=flodiebold Co-authored-by: Florian Diebold <flodiebold@gmail.com>
2 parents 86d2af9 + 2c11a9b commit 21be386

File tree

3 files changed

+55
-19
lines changed

3 files changed

+55
-19
lines changed

crates/ra_assists/src/assists/fill_match_arms.rs

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,24 @@ pub(crate) fn fill_match_arms(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
4646
};
4747

4848
let expr = match_expr.expr()?;
49-
let enum_def = {
49+
let (enum_def, module) = {
5050
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()?)
5252
};
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;
5459

5560
ctx.add_assist(AssistId("fill_match_arms"), "fill match arms", |edit| {
5661
let indent_level = IndentLevel::from_node(match_arm_list.syntax());
5762

5863
let new_arm_list = {
59-
let variants = variant_list.variants();
6064
let arms = variants
61-
.filter_map(build_pat)
65+
.into_iter()
66+
.filter_map(|variant| build_pat(db, module, variant))
6267
.map(|pat| make::match_arm(iter::once(pat), make::expr_unit()));
6368
indent_level.increase_indent(make::match_arm_list(arms))
6469
};
@@ -80,23 +85,25 @@ fn resolve_enum_def(
8085
db: &impl HirDatabase,
8186
analyzer: &hir::SourceAnalyzer,
8287
expr: &ast::Expr,
83-
) -> Option<ast::EnumDef> {
88+
) -> Option<hir::Enum> {
8489
let expr_ty = analyzer.type_of(db, &expr)?;
8590

86-
let res = expr_ty.autoderef(db).find_map(|ty| match ty.as_adt() {
87-
Some(Adt::Enum(e)) => Some(e.source(db).value),
91+
let result = expr_ty.autoderef(db).find_map(|ty| match ty.as_adt() {
92+
Some(Adt::Enum(e)) => Some(e),
8893
_ => None,
8994
});
90-
res
95+
result
9196
}
9297

93-
fn build_pat(var: ast::EnumVariant) -> Option<ast::Pat> {
94-
let path = make::path_qualified(
95-
make::path_from_name_ref(make::name_ref(&var.parent_enum().name()?.syntax().to_string())),
96-
make::name_ref(&var.name()?.syntax().to_string()),
97-
);
98+
fn build_pat(
99+
db: &impl HirDatabase,
100+
module: hir::Module,
101+
var: hir::EnumVariant,
102+
) -> Option<ast::Pat> {
103+
let path = crate::ast_transform::path_to_ast(module.find_use_path(db, var.into())?);
98104

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() {
100107
ast::StructKind::Tuple(field_list) => {
101108
let pats =
102109
iter::repeat(make::placeholder_pat().into()).take(field_list.fields().count());
@@ -106,7 +113,7 @@ fn build_pat(var: ast::EnumVariant) -> Option<ast::Pat> {
106113
let pats = field_list.fields().map(|f| make::bind_pat(f.name().unwrap()).into());
107114
make::record_pat(path, pats).into()
108115
}
109-
ast::StructKind::Unit => make::path_pat(path).into(),
116+
ast::StructKind::Unit => make::path_pat(path),
110117
};
111118

112119
Some(pat)
@@ -252,4 +259,32 @@ mod tests {
252259
"#,
253260
);
254261
}
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+
}
255290
}

crates/ra_assists/src/ast_transform.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ impl<'a, DB: HirDatabase> AstTransform<'a> for QualifyPaths<'a, DB> {
173173
}
174174
}
175175

176-
fn path_to_ast(path: hir::ModPath) -> ast::Path {
176+
pub(crate) fn path_to_ast(path: hir::ModPath) -> ast::Path {
177177
let parse = ast::SourceFile::parse(&path.to_string());
178178
parse.tree().syntax().descendants().find_map(ast::Path::cast).unwrap()
179179
}

crates/ra_syntax/src/ast/make.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,11 @@ pub fn record_pat(path: ast::Path, pats: impl IntoIterator<Item = ast::Pat>) ->
117117
}
118118
}
119119

120-
pub fn path_pat(path: ast::Path) -> ast::PathPat {
120+
/// Returns a `BindPat` if the path has just one segment, a `PathPat` otherwise.
121+
pub fn path_pat(path: ast::Path) -> ast::Pat {
121122
let path_str = path.syntax().text().to_string();
122123
return from_text(path_str.as_str());
123-
fn from_text(text: &str) -> ast::PathPat {
124+
fn from_text(text: &str) -> ast::Pat {
124125
ast_from_text(&format!("fn f({}: ())", text))
125126
}
126127
}

0 commit comments

Comments
 (0)