From 2c11a9b42deca002bcd4a669dcbb3ab972b939d8 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 10 Jan 2020 21:42:04 +0100 Subject: Qualify paths in 'fill match arms' assist --- crates/ra_assists/src/assists/fill_match_arms.rs | 67 ++++++++++++++++++------ crates/ra_assists/src/ast_transform.rs | 2 +- crates/ra_syntax/src/ast/make.rs | 5 +- 3 files changed, 55 insertions(+), 19 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) -> Option Option { +) -> Option { let expr_ty = analyzer.type_of(db, &expr)?; - let res = expr_ty.autoderef(db).find_map(|ty| match ty.as_adt() { - Some(Adt::Enum(e)) => Some(e.source(db).value), + let result = expr_ty.autoderef(db).find_map(|ty| match ty.as_adt() { + Some(Adt::Enum(e)) => Some(e), _ => None, }); - res + result } -fn build_pat(var: ast::EnumVariant) -> Option { - let path = make::path_qualified( - make::path_from_name_ref(make::name_ref(&var.parent_enum().name()?.syntax().to_string())), - make::name_ref(&var.name()?.syntax().to_string()), - ); +fn build_pat( + db: &impl HirDatabase, + module: hir::Module, + var: hir::EnumVariant, +) -> Option { + let path = crate::ast_transform::path_to_ast(module.find_use_path(db, var.into())?); - let pat: ast::Pat = match var.kind() { + // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though + let pat: ast::Pat = match var.source(db).value.kind() { ast::StructKind::Tuple(field_list) => { let pats = iter::repeat(make::placeholder_pat().into()).take(field_list.fields().count()); @@ -106,7 +113,7 @@ fn build_pat(var: ast::EnumVariant) -> Option { let pats = field_list.fields().map(|f| make::bind_pat(f.name().unwrap()).into()); make::record_pat(path, pats).into() } - ast::StructKind::Unit => make::path_pat(path).into(), + ast::StructKind::Unit => make::path_pat(path), }; Some(pat) @@ -252,4 +259,32 @@ mod tests { "#, ); } + + #[test] + fn fill_match_arms_qualifies_path() { + check_assist( + fill_match_arms, + r#" + mod foo { pub enum E { X, Y } } + use foo::E::X; + + fn main() { + match X { + <|> + } + } + "#, + r#" + mod foo { pub enum E { X, Y } } + use foo::E::X; + + fn main() { + match <|>X { + X => (), + foo::E::Y => (), + } + } + "#, + ); + } } diff --git a/crates/ra_assists/src/ast_transform.rs b/crates/ra_assists/src/ast_transform.rs index cbddc50ac..eac2903d1 100644 --- a/crates/ra_assists/src/ast_transform.rs +++ b/crates/ra_assists/src/ast_transform.rs @@ -173,7 +173,7 @@ impl<'a, DB: HirDatabase> AstTransform<'a> for QualifyPaths<'a, DB> { } } -fn path_to_ast(path: hir::ModPath) -> ast::Path { +pub(crate) fn path_to_ast(path: hir::ModPath) -> ast::Path { let parse = ast::SourceFile::parse(&path.to_string()); parse.tree().syntax().descendants().find_map(ast::Path::cast).unwrap() } diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 9781b748f..eef45090d 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs @@ -117,10 +117,11 @@ pub fn record_pat(path: ast::Path, pats: impl IntoIterator) -> } } -pub fn path_pat(path: ast::Path) -> ast::PathPat { +/// Returns a `BindPat` if the path has just one segment, a `PathPat` otherwise. +pub fn path_pat(path: ast::Path) -> ast::Pat { let path_str = path.syntax().text().to_string(); return from_text(path_str.as_str()); - fn from_text(text: &str) -> ast::PathPat { + fn from_text(text: &str) -> ast::Pat { ast_from_text(&format!("fn f({}: ())", text)) } } -- cgit v1.2.3