aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists
diff options
context:
space:
mode:
authorDmitry <[email protected]>2020-08-09 14:35:51 +0100
committerDmitry <[email protected]>2020-08-09 14:39:32 +0100
commit8068302fefc75440b823f4bf1731a5f347d7c767 (patch)
tree251b967182e79bc82a58c2fb208c688f6152df1f /crates/ra_assists
parent1a43a0f63e0008787225abb6fb2baef97b6a39e0 (diff)
parent8a57afe5a4bfab40072a83f7dc4ca560bf860919 (diff)
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'crates/ra_assists')
-rw-r--r--crates/ra_assists/src/assist_context.rs4
-rw-r--r--crates/ra_assists/src/ast_transform.rs34
-rw-r--r--crates/ra_assists/src/handlers/add_custom_impl.rs4
-rw-r--r--crates/ra_assists/src/handlers/add_explicit_type.rs20
-rw-r--r--crates/ra_assists/src/handlers/add_missing_impl_members.rs29
-rw-r--r--crates/ra_assists/src/handlers/auto_import.rs2
-rw-r--r--crates/ra_assists/src/handlers/change_return_type_to_result.rs9
-rw-r--r--crates/ra_assists/src/handlers/change_visibility.rs10
-rw-r--r--crates/ra_assists/src/handlers/early_return.rs14
-rw-r--r--crates/ra_assists/src/handlers/expand_glob_import.rs391
-rw-r--r--crates/ra_assists/src/handlers/extract_struct_from_enum_variant.rs2
-rw-r--r--crates/ra_assists/src/handlers/extract_variable.rs6
-rw-r--r--crates/ra_assists/src/handlers/fill_match_arms.rs29
-rw-r--r--crates/ra_assists/src/handlers/fix_visibility.rs2
-rw-r--r--crates/ra_assists/src/handlers/generate_derive.rs4
-rw-r--r--crates/ra_assists/src/handlers/generate_from_impl_for_enum.rs8
-rw-r--r--crates/ra_assists/src/handlers/generate_function.rs8
-rw-r--r--crates/ra_assists/src/handlers/generate_impl.rs6
-rw-r--r--crates/ra_assists/src/handlers/generate_new.rs24
-rw-r--r--crates/ra_assists/src/handlers/inline_local_variable.rs2
-rw-r--r--crates/ra_assists/src/handlers/introduce_named_lifetime.rs24
-rw-r--r--crates/ra_assists/src/handlers/merge_imports.rs2
-rw-r--r--crates/ra_assists/src/handlers/merge_match_arms.rs2
-rw-r--r--crates/ra_assists/src/handlers/move_bounds.rs14
-rw-r--r--crates/ra_assists/src/handlers/raw_string.rs2
-rw-r--r--crates/ra_assists/src/handlers/remove_dbg.rs94
-rw-r--r--crates/ra_assists/src/handlers/reorder_fields.rs10
-rw-r--r--crates/ra_assists/src/handlers/replace_if_let_with_match.rs2
-rw-r--r--crates/ra_assists/src/handlers/replace_let_with_if_let.rs7
-rw-r--r--crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs46
-rw-r--r--crates/ra_assists/src/handlers/replace_unwrap_with_match.rs4
-rw-r--r--crates/ra_assists/src/lib.rs2
-rw-r--r--crates/ra_assists/src/tests/generated.rs27
-rw-r--r--crates/ra_assists/src/utils.rs24
-rw-r--r--crates/ra_assists/src/utils/insert_use.rs13
35 files changed, 709 insertions, 172 deletions
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs
index 3407df856..afd3fd4b9 100644
--- a/crates/ra_assists/src/assist_context.rs
+++ b/crates/ra_assists/src/assist_context.rs
@@ -73,6 +73,10 @@ impl<'a> AssistContext<'a> {
73 self.sema.db 73 self.sema.db
74 } 74 }
75 75
76 pub(crate) fn source_file(&self) -> &SourceFile {
77 &self.source_file
78 }
79
76 // NB, this ignores active selection. 80 // NB, this ignores active selection.
77 pub(crate) fn offset(&self) -> TextSize { 81 pub(crate) fn offset(&self) -> TextSize {
78 self.frange.range.start() 82 self.frange.range.start()
diff --git a/crates/ra_assists/src/ast_transform.rs b/crates/ra_assists/src/ast_transform.rs
index 01adb834c..15ec75c95 100644
--- a/crates/ra_assists/src/ast_transform.rs
+++ b/crates/ra_assists/src/ast_transform.rs
@@ -32,7 +32,7 @@ impl<'a> AstTransform<'a> for NullTransformer {
32 32
33pub struct SubstituteTypeParams<'a> { 33pub struct SubstituteTypeParams<'a> {
34 source_scope: &'a SemanticsScope<'a>, 34 source_scope: &'a SemanticsScope<'a>,
35 substs: FxHashMap<hir::TypeParam, ast::TypeRef>, 35 substs: FxHashMap<hir::TypeParam, ast::Type>,
36 previous: Box<dyn AstTransform<'a> + 'a>, 36 previous: Box<dyn AstTransform<'a> + 'a>,
37} 37}
38 38
@@ -41,7 +41,7 @@ impl<'a> SubstituteTypeParams<'a> {
41 source_scope: &'a SemanticsScope<'a>, 41 source_scope: &'a SemanticsScope<'a>,
42 // FIXME: there's implicit invariant that `trait_` and `source_scope` match... 42 // FIXME: there's implicit invariant that `trait_` and `source_scope` match...
43 trait_: hir::Trait, 43 trait_: hir::Trait,
44 impl_def: ast::ImplDef, 44 impl_def: ast::Impl,
45 ) -> SubstituteTypeParams<'a> { 45 ) -> SubstituteTypeParams<'a> {
46 let substs = get_syntactic_substs(impl_def).unwrap_or_default(); 46 let substs = get_syntactic_substs(impl_def).unwrap_or_default();
47 let generic_def: hir::GenericDef = trait_.into(); 47 let generic_def: hir::GenericDef = trait_.into();
@@ -63,7 +63,7 @@ impl<'a> SubstituteTypeParams<'a> {
63 let default = k.default(source_scope.db)?; 63 let default = k.default(source_scope.db)?;
64 Some(( 64 Some((
65 k, 65 k,
66 ast::make::type_ref( 66 ast::make::ty(
67 &default 67 &default
68 .display_source_code(source_scope.db, source_scope.module()?.into()) 68 .display_source_code(source_scope.db, source_scope.module()?.into())
69 .ok()?, 69 .ok()?,
@@ -79,19 +79,25 @@ impl<'a> SubstituteTypeParams<'a> {
79 }; 79 };
80 80
81 // FIXME: It would probably be nicer if we could get this via HIR (i.e. get the 81 // FIXME: It would probably be nicer if we could get this via HIR (i.e. get the
82 // trait ref, and then go from the types in the substs back to the syntax) 82 // trait ref, and then go from the types in the substs back to the syntax).
83 fn get_syntactic_substs(impl_def: ast::ImplDef) -> Option<Vec<ast::TypeRef>> { 83 fn get_syntactic_substs(impl_def: ast::Impl) -> Option<Vec<ast::Type>> {
84 let target_trait = impl_def.target_trait()?; 84 let target_trait = impl_def.trait_()?;
85 let path_type = match target_trait { 85 let path_type = match target_trait {
86 ast::TypeRef::PathType(path) => path, 86 ast::Type::PathType(path) => path,
87 _ => return None, 87 _ => return None,
88 }; 88 };
89 let type_arg_list = path_type.path()?.segment()?.type_arg_list()?; 89 let generic_arg_list = path_type.path()?.segment()?.generic_arg_list()?;
90
90 let mut result = Vec::new(); 91 let mut result = Vec::new();
91 for type_arg in type_arg_list.type_args() { 92 for generic_arg in generic_arg_list.generic_args() {
92 let type_arg: ast::TypeArg = type_arg; 93 match generic_arg {
93 result.push(type_arg.type_ref()?); 94 ast::GenericArg::TypeArg(type_arg) => result.push(type_arg.ty()?),
95 ast::GenericArg::AssocTypeArg(_)
96 | ast::GenericArg::LifetimeArg(_)
97 | ast::GenericArg::ConstArg(_) => (),
98 }
94 } 99 }
100
95 Some(result) 101 Some(result)
96 } 102 }
97 } 103 }
@@ -99,9 +105,9 @@ impl<'a> SubstituteTypeParams<'a> {
99 &self, 105 &self,
100 node: &ra_syntax::SyntaxNode, 106 node: &ra_syntax::SyntaxNode,
101 ) -> Option<ra_syntax::SyntaxNode> { 107 ) -> Option<ra_syntax::SyntaxNode> {
102 let type_ref = ast::TypeRef::cast(node.clone())?; 108 let type_ref = ast::Type::cast(node.clone())?;
103 let path = match &type_ref { 109 let path = match &type_ref {
104 ast::TypeRef::PathType(path_type) => path_type.path()?, 110 ast::Type::PathType(path_type) => path_type.path()?,
105 _ => return None, 111 _ => return None,
106 }; 112 };
107 // FIXME: use `hir::Path::from_src` instead. 113 // FIXME: use `hir::Path::from_src` instead.
@@ -157,7 +163,7 @@ impl<'a> QualifyPaths<'a> {
157 163
158 let type_args = p 164 let type_args = p
159 .segment() 165 .segment()
160 .and_then(|s| s.type_arg_list()) 166 .and_then(|s| s.generic_arg_list())
161 .map(|arg_list| apply(self, arg_list)); 167 .map(|arg_list| apply(self, arg_list));
162 if let Some(type_args) = type_args { 168 if let Some(type_args) = type_args {
163 let last_segment = path.segment().unwrap(); 169 let last_segment = path.segment().unwrap();
diff --git a/crates/ra_assists/src/handlers/add_custom_impl.rs b/crates/ra_assists/src/handlers/add_custom_impl.rs
index acb07e36a..b67438b6b 100644
--- a/crates/ra_assists/src/handlers/add_custom_impl.rs
+++ b/crates/ra_assists/src/handlers/add_custom_impl.rs
@@ -29,8 +29,8 @@ use crate::{
29// } 29// }
30// ``` 30// ```
31pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 31pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
32 let input = ctx.find_node_at_offset::<ast::AttrInput>()?; 32 let attr = ctx.find_node_at_offset::<ast::Attr>()?;
33 let attr = input.syntax().parent().and_then(ast::Attr::cast)?; 33 let input = attr.token_tree()?;
34 34
35 let attr_name = attr 35 let attr_name = attr
36 .syntax() 36 .syntax()
diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs
index 39a5321d1..135a2ac9c 100644
--- a/crates/ra_assists/src/handlers/add_explicit_type.rs
+++ b/crates/ra_assists/src/handlers/add_explicit_type.rs
@@ -1,6 +1,6 @@
1use hir::HirDisplay; 1use hir::HirDisplay;
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, AstNode, LetStmt, NameOwner, TypeAscriptionOwner}, 3 ast::{self, AstNode, LetStmt, NameOwner},
4 TextRange, 4 TextRange,
5}; 5};
6 6
@@ -22,20 +22,20 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
22// } 22// }
23// ``` 23// ```
24pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 24pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
25 let stmt = ctx.find_node_at_offset::<LetStmt>()?; 25 let let_stmt = ctx.find_node_at_offset::<LetStmt>()?;
26 let module = ctx.sema.scope(stmt.syntax()).module()?; 26 let module = ctx.sema.scope(let_stmt.syntax()).module()?;
27 let expr = stmt.initializer()?; 27 let expr = let_stmt.initializer()?;
28 // Must be a binding 28 // Must be a binding
29 let pat = match stmt.pat()? { 29 let pat = match let_stmt.pat()? {
30 ast::Pat::BindPat(bind_pat) => bind_pat, 30 ast::Pat::IdentPat(bind_pat) => bind_pat,
31 _ => return None, 31 _ => return None,
32 }; 32 };
33 let pat_range = pat.syntax().text_range(); 33 let pat_range = pat.syntax().text_range();
34 // The binding must have a name 34 // The binding must have a name
35 let name = pat.name()?; 35 let name = pat.name()?;
36 let name_range = name.syntax().text_range(); 36 let name_range = name.syntax().text_range();
37 let stmt_range = stmt.syntax().text_range(); 37 let stmt_range = let_stmt.syntax().text_range();
38 let eq_range = stmt.eq_token()?.text_range(); 38 let eq_range = let_stmt.eq_token()?.text_range();
39 // Assist should only be applicable if cursor is between 'let' and '=' 39 // Assist should only be applicable if cursor is between 'let' and '='
40 let let_range = TextRange::new(stmt_range.start(), eq_range.start()); 40 let let_range = TextRange::new(stmt_range.start(), eq_range.start());
41 let cursor_in_range = let_range.contains_range(ctx.frange.range); 41 let cursor_in_range = let_range.contains_range(ctx.frange.range);
@@ -44,9 +44,9 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio
44 } 44 }
45 // Assist not applicable if the type has already been specified 45 // Assist not applicable if the type has already been specified
46 // and it has no placeholders 46 // and it has no placeholders
47 let ascribed_ty = stmt.ascribed_type(); 47 let ascribed_ty = let_stmt.ty();
48 if let Some(ty) = &ascribed_ty { 48 if let Some(ty) = &ascribed_ty {
49 if ty.syntax().descendants().find_map(ast::PlaceholderType::cast).is_none() { 49 if ty.syntax().descendants().find_map(ast::InferType::cast).is_none() {
50 return None; 50 return None;
51 } 51 }
52 } 52 }
diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
index f185e61e5..95a750aee 100644
--- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
@@ -111,16 +111,17 @@ fn add_missing_impl_members_inner(
111 label: &'static str, 111 label: &'static str,
112) -> Option<()> { 112) -> Option<()> {
113 let _p = ra_prof::profile("add_missing_impl_members_inner"); 113 let _p = ra_prof::profile("add_missing_impl_members_inner");
114 let impl_def = ctx.find_node_at_offset::<ast::ImplDef>()?; 114 let impl_def = ctx.find_node_at_offset::<ast::Impl>()?;
115 let impl_item_list = impl_def.item_list()?; 115 let impl_item_list = impl_def.assoc_item_list()?;
116 116
117 let trait_ = resolve_target_trait(&ctx.sema, &impl_def)?; 117 let trait_ = resolve_target_trait(&ctx.sema, &impl_def)?;
118 118
119 let def_name = |item: &ast::AssocItem| -> Option<SmolStr> { 119 let def_name = |item: &ast::AssocItem| -> Option<SmolStr> {
120 match item { 120 match item {
121 ast::AssocItem::FnDef(def) => def.name(), 121 ast::AssocItem::Fn(def) => def.name(),
122 ast::AssocItem::TypeAliasDef(def) => def.name(), 122 ast::AssocItem::TypeAlias(def) => def.name(),
123 ast::AssocItem::ConstDef(def) => def.name(), 123 ast::AssocItem::Const(def) => def.name(),
124 ast::AssocItem::MacroCall(_) => None,
124 } 125 }
125 .map(|it| it.text().clone()) 126 .map(|it| it.text().clone())
126 }; 127 };
@@ -128,13 +129,13 @@ fn add_missing_impl_members_inner(
128 let missing_items = get_missing_assoc_items(&ctx.sema, &impl_def) 129 let missing_items = get_missing_assoc_items(&ctx.sema, &impl_def)
129 .iter() 130 .iter()
130 .map(|i| match i { 131 .map(|i| match i {
131 hir::AssocItem::Function(i) => ast::AssocItem::FnDef(i.source(ctx.db()).value), 132 hir::AssocItem::Function(i) => ast::AssocItem::Fn(i.source(ctx.db()).value),
132 hir::AssocItem::TypeAlias(i) => ast::AssocItem::TypeAliasDef(i.source(ctx.db()).value), 133 hir::AssocItem::TypeAlias(i) => ast::AssocItem::TypeAlias(i.source(ctx.db()).value),
133 hir::AssocItem::Const(i) => ast::AssocItem::ConstDef(i.source(ctx.db()).value), 134 hir::AssocItem::Const(i) => ast::AssocItem::Const(i.source(ctx.db()).value),
134 }) 135 })
135 .filter(|t| def_name(&t).is_some()) 136 .filter(|t| def_name(&t).is_some())
136 .filter(|t| match t { 137 .filter(|t| match t {
137 ast::AssocItem::FnDef(def) => match mode { 138 ast::AssocItem::Fn(def) => match mode {
138 AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(), 139 AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(),
139 AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(), 140 AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(),
140 }, 141 },
@@ -157,10 +158,8 @@ fn add_missing_impl_members_inner(
157 .into_iter() 158 .into_iter()
158 .map(|it| ast_transform::apply(&*ast_transform, it)) 159 .map(|it| ast_transform::apply(&*ast_transform, it))
159 .map(|it| match it { 160 .map(|it| match it {
160 ast::AssocItem::FnDef(def) => ast::AssocItem::FnDef(add_body(def)), 161 ast::AssocItem::Fn(def) => ast::AssocItem::Fn(add_body(def)),
161 ast::AssocItem::TypeAliasDef(def) => { 162 ast::AssocItem::TypeAlias(def) => ast::AssocItem::TypeAlias(def.remove_bounds()),
162 ast::AssocItem::TypeAliasDef(def.remove_bounds())
163 }
164 _ => it, 163 _ => it,
165 }) 164 })
166 .map(|it| edit::remove_attrs_and_docs(&it)); 165 .map(|it| edit::remove_attrs_and_docs(&it));
@@ -173,7 +172,7 @@ fn add_missing_impl_members_inner(
173 Some(cap) => { 172 Some(cap) => {
174 let mut cursor = Cursor::Before(first_new_item.syntax()); 173 let mut cursor = Cursor::Before(first_new_item.syntax());
175 let placeholder; 174 let placeholder;
176 if let ast::AssocItem::FnDef(func) = &first_new_item { 175 if let ast::AssocItem::Fn(func) = &first_new_item {
177 if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast) { 176 if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast) {
178 if m.syntax().text() == "todo!()" { 177 if m.syntax().text() == "todo!()" {
179 placeholder = m; 178 placeholder = m;
@@ -191,7 +190,7 @@ fn add_missing_impl_members_inner(
191 }) 190 })
192} 191}
193 192
194fn add_body(fn_def: ast::FnDef) -> ast::FnDef { 193fn add_body(fn_def: ast::Fn) -> ast::Fn {
195 if fn_def.body().is_some() { 194 if fn_def.body().is_some() {
196 return fn_def; 195 return fn_def;
197 } 196 }
diff --git a/crates/ra_assists/src/handlers/auto_import.rs b/crates/ra_assists/src/handlers/auto_import.rs
index 947be3b9b..01e7b7a44 100644
--- a/crates/ra_assists/src/handlers/auto_import.rs
+++ b/crates/ra_assists/src/handlers/auto_import.rs
@@ -92,7 +92,7 @@ impl AutoImportAssets {
92 92
93 fn for_regular_path(path_under_caret: ast::Path, ctx: &AssistContext) -> Option<Self> { 93 fn for_regular_path(path_under_caret: ast::Path, ctx: &AssistContext) -> Option<Self> {
94 let syntax_under_caret = path_under_caret.syntax().to_owned(); 94 let syntax_under_caret = path_under_caret.syntax().to_owned();
95 if syntax_under_caret.ancestors().find_map(ast::UseItem::cast).is_some() { 95 if syntax_under_caret.ancestors().find_map(ast::Use::cast).is_some() {
96 return None; 96 return None;
97 } 97 }
98 98
diff --git a/crates/ra_assists/src/handlers/change_return_type_to_result.rs b/crates/ra_assists/src/handlers/change_return_type_to_result.rs
index def00f7d8..b83c94404 100644
--- a/crates/ra_assists/src/handlers/change_return_type_to_result.rs
+++ b/crates/ra_assists/src/handlers/change_return_type_to_result.rs
@@ -20,9 +20,9 @@ use test_utils::mark;
20pub(crate) fn change_return_type_to_result(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 20pub(crate) fn change_return_type_to_result(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
21 let ret_type = ctx.find_node_at_offset::<ast::RetType>()?; 21 let ret_type = ctx.find_node_at_offset::<ast::RetType>()?;
22 // FIXME: extend to lambdas as well 22 // FIXME: extend to lambdas as well
23 let fn_def = ret_type.syntax().parent().and_then(ast::FnDef::cast)?; 23 let fn_def = ret_type.syntax().parent().and_then(ast::Fn::cast)?;
24 24
25 let type_ref = &ret_type.type_ref()?; 25 let type_ref = &ret_type.ty()?;
26 let ret_type_str = type_ref.syntax().text().to_string(); 26 let ret_type_str = type_ref.syntax().text().to_string();
27 let first_part_ret_type = ret_type_str.splitn(2, '<').next(); 27 let first_part_ret_type = ret_type_str.splitn(2, '<').next();
28 if let Some(ret_type_first_part) = first_part_ret_type { 28 if let Some(ret_type_first_part) = first_part_ret_type {
@@ -74,6 +74,7 @@ impl TailReturnCollector {
74 let expr = match &stmt { 74 let expr = match &stmt {
75 ast::Stmt::ExprStmt(stmt) => stmt.expr(), 75 ast::Stmt::ExprStmt(stmt) => stmt.expr(),
76 ast::Stmt::LetStmt(stmt) => stmt.initializer(), 76 ast::Stmt::LetStmt(stmt) => stmt.initializer(),
77 ast::Stmt::Item(_) => continue,
77 }; 78 };
78 if let Some(expr) = &expr { 79 if let Some(expr) = &expr {
79 self.handle_exprs(expr, collect_break); 80 self.handle_exprs(expr, collect_break);
@@ -94,6 +95,7 @@ impl TailReturnCollector {
94 let expr_stmt = match &expr_stmt { 95 let expr_stmt = match &expr_stmt {
95 ast::Stmt::ExprStmt(stmt) => stmt.expr(), 96 ast::Stmt::ExprStmt(stmt) => stmt.expr(),
96 ast::Stmt::LetStmt(stmt) => stmt.initializer(), 97 ast::Stmt::LetStmt(stmt) => stmt.initializer(),
98 ast::Stmt::Item(_) => None,
97 }; 99 };
98 if let Some(expr) = &expr_stmt { 100 if let Some(expr) = &expr_stmt {
99 self.handle_exprs(expr, collect_break); 101 self.handle_exprs(expr, collect_break);
@@ -239,8 +241,7 @@ fn get_tail_expr_from_block(expr: &Expr) -> Option<Vec<NodeType>> {
239 Expr::ArrayExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 241 Expr::ArrayExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
240 Expr::ParenExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 242 Expr::ParenExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
241 Expr::PathExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 243 Expr::PathExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
242 Expr::Label(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 244 Expr::RecordExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
243 Expr::RecordLit(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
244 Expr::IndexExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 245 Expr::IndexExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
245 Expr::MethodCallExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 246 Expr::MethodCallExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
246 Expr::AwaitExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 247 Expr::AwaitExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
diff --git a/crates/ra_assists/src/handlers/change_visibility.rs b/crates/ra_assists/src/handlers/change_visibility.rs
index 4343b423c..724daa93f 100644
--- a/crates/ra_assists/src/handlers/change_visibility.rs
+++ b/crates/ra_assists/src/handlers/change_visibility.rs
@@ -1,9 +1,7 @@
1use ra_syntax::{ 1use ra_syntax::{
2 ast::{self, NameOwner, VisibilityOwner}, 2 ast::{self, NameOwner, VisibilityOwner},
3 AstNode, 3 AstNode,
4 SyntaxKind::{ 4 SyntaxKind::{CONST, ENUM, FN, MODULE, STATIC, STRUCT, TRAIT, VISIBILITY},
5 CONST_DEF, ENUM_DEF, FN_DEF, MODULE, STATIC_DEF, STRUCT_DEF, TRAIT_DEF, VISIBILITY,
6 },
7 T, 5 T,
8}; 6};
9use test_utils::mark; 7use test_utils::mark;
@@ -38,7 +36,7 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
38 36
39 let (offset, target) = if let Some(keyword) = item_keyword { 37 let (offset, target) = if let Some(keyword) = item_keyword {
40 let parent = keyword.parent(); 38 let parent = keyword.parent();
41 let def_kws = vec![CONST_DEF, STATIC_DEF, FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF]; 39 let def_kws = vec![CONST, STATIC, FN, MODULE, STRUCT, ENUM, TRAIT];
42 // Parent is not a definition, can't add visibility 40 // Parent is not a definition, can't add visibility
43 if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) { 41 if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) {
44 return None; 42 return None;
@@ -49,7 +47,7 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
49 } 47 }
50 (vis_offset(&parent), keyword.text_range()) 48 (vis_offset(&parent), keyword.text_range())
51 } else if let Some(field_name) = ctx.find_node_at_offset::<ast::Name>() { 49 } else if let Some(field_name) = ctx.find_node_at_offset::<ast::Name>() {
52 let field = field_name.syntax().ancestors().find_map(ast::RecordFieldDef::cast)?; 50 let field = field_name.syntax().ancestors().find_map(ast::RecordField::cast)?;
53 if field.name()? != field_name { 51 if field.name()? != field_name {
54 mark::hit!(change_visibility_field_false_positive); 52 mark::hit!(change_visibility_field_false_positive);
55 return None; 53 return None;
@@ -58,7 +56,7 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
58 return None; 56 return None;
59 } 57 }
60 (vis_offset(field.syntax()), field_name.syntax().text_range()) 58 (vis_offset(field.syntax()), field_name.syntax().text_range())
61 } else if let Some(field) = ctx.find_node_at_offset::<ast::TupleFieldDef>() { 59 } else if let Some(field) = ctx.find_node_at_offset::<ast::TupleField>() {
62 if field.visibility().is_some() { 60 if field.visibility().is_some() {
63 return None; 61 return None;
64 } 62 }
diff --git a/crates/ra_assists/src/handlers/early_return.rs b/crates/ra_assists/src/handlers/early_return.rs
index 330459f3c..6816a2709 100644
--- a/crates/ra_assists/src/handlers/early_return.rs
+++ b/crates/ra_assists/src/handlers/early_return.rs
@@ -8,7 +8,7 @@ use ra_syntax::{
8 make, 8 make,
9 }, 9 },
10 AstNode, 10 AstNode,
11 SyntaxKind::{FN_DEF, LOOP_EXPR, L_CURLY, R_CURLY, WHILE_EXPR, WHITESPACE}, 11 SyntaxKind::{FN, LOOP_EXPR, L_CURLY, R_CURLY, WHILE_EXPR, WHITESPACE},
12 SyntaxNode, 12 SyntaxNode,
13}; 13};
14 14
@@ -51,11 +51,11 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
51 // Check if there is an IfLet that we can handle. 51 // Check if there is an IfLet that we can handle.
52 let if_let_pat = match cond.pat() { 52 let if_let_pat = match cond.pat() {
53 None => None, // No IfLet, supported. 53 None => None, // No IfLet, supported.
54 Some(ast::Pat::TupleStructPat(pat)) if pat.args().count() == 1 => { 54 Some(ast::Pat::TupleStructPat(pat)) if pat.fields().count() == 1 => {
55 let path = pat.path()?; 55 let path = pat.path()?;
56 match path.qualifier() { 56 match path.qualifier() {
57 None => { 57 None => {
58 let bound_ident = pat.args().next().unwrap(); 58 let bound_ident = pat.fields().next().unwrap();
59 Some((path, bound_ident)) 59 Some((path, bound_ident))
60 } 60 }
61 Some(_) => return None, 61 Some(_) => return None,
@@ -88,7 +88,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
88 88
89 let early_expression: ast::Expr = match parent_container.kind() { 89 let early_expression: ast::Expr = match parent_container.kind() {
90 WHILE_EXPR | LOOP_EXPR => make::expr_continue(), 90 WHILE_EXPR | LOOP_EXPR => make::expr_continue(),
91 FN_DEF => make::expr_return(), 91 FN => make::expr_return(),
92 _ => return None, 92 _ => return None,
93 }; 93 };
94 94
@@ -123,7 +123,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
123 let happy_arm = { 123 let happy_arm = {
124 let pat = make::tuple_struct_pat( 124 let pat = make::tuple_struct_pat(
125 path, 125 path,
126 once(make::bind_pat(make::name("it")).into()), 126 once(make::ident_pat(make::name("it")).into()),
127 ); 127 );
128 let expr = { 128 let expr = {
129 let name_ref = make::name_ref("it"); 129 let name_ref = make::name_ref("it");
@@ -136,7 +136,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
136 136
137 let sad_arm = make::match_arm( 137 let sad_arm = make::match_arm(
138 // FIXME: would be cool to use `None` or `Err(_)` if appropriate 138 // FIXME: would be cool to use `None` or `Err(_)` if appropriate
139 once(make::placeholder_pat().into()), 139 once(make::wildcard_pat().into()),
140 early_expression, 140 early_expression,
141 ); 141 );
142 142
@@ -144,7 +144,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
144 }; 144 };
145 145
146 let let_stmt = make::let_stmt( 146 let let_stmt = make::let_stmt(
147 make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(), 147 make::ident_pat(make::name(&bound_ident.syntax().to_string())).into(),
148 Some(match_expr), 148 Some(match_expr),
149 ); 149 );
150 let let_stmt = let_stmt.indent(if_indent_level); 150 let let_stmt = let_stmt.indent(if_indent_level);
diff --git a/crates/ra_assists/src/handlers/expand_glob_import.rs b/crates/ra_assists/src/handlers/expand_glob_import.rs
new file mode 100644
index 000000000..eb216a81a
--- /dev/null
+++ b/crates/ra_assists/src/handlers/expand_glob_import.rs
@@ -0,0 +1,391 @@
1use hir::{AssocItem, MacroDef, ModuleDef, Name, PathResolution, ScopeDef, SemanticsScope};
2use ra_ide_db::{
3 defs::{classify_name_ref, Definition, NameRefClass},
4 RootDatabase,
5};
6use ra_syntax::{algo, ast, match_ast, AstNode, SyntaxNode, SyntaxToken, T};
7
8use crate::{
9 assist_context::{AssistBuilder, AssistContext, Assists},
10 AssistId, AssistKind,
11};
12
13use either::Either;
14
15// Assist: expand_glob_import
16//
17// Expands glob imports.
18//
19// ```
20// mod foo {
21// pub struct Bar;
22// pub struct Baz;
23// }
24//
25// use foo::*<|>;
26//
27// fn qux(bar: Bar, baz: Baz) {}
28// ```
29// ->
30// ```
31// mod foo {
32// pub struct Bar;
33// pub struct Baz;
34// }
35//
36// use foo::{Baz, Bar};
37//
38// fn qux(bar: Bar, baz: Baz) {}
39// ```
40pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
41 let star = ctx.find_token_at_offset(T![*])?;
42 let mod_path = find_mod_path(&star)?;
43
44 let source_file = ctx.source_file();
45 let scope = ctx.sema.scope_at_offset(source_file.syntax(), ctx.offset());
46
47 let defs_in_mod = find_defs_in_mod(ctx, scope, &mod_path)?;
48 let name_refs_in_source_file =
49 source_file.syntax().descendants().filter_map(ast::NameRef::cast).collect();
50 let used_names = find_used_names(ctx, defs_in_mod, name_refs_in_source_file);
51
52 let parent = star.parent().parent()?;
53 acc.add(
54 AssistId("expand_glob_import", AssistKind::RefactorRewrite),
55 "Expand glob import",
56 parent.text_range(),
57 |builder| {
58 replace_ast(builder, &parent, mod_path, used_names);
59 },
60 )
61}
62
63fn find_mod_path(star: &SyntaxToken) -> Option<ast::Path> {
64 star.ancestors().find_map(|n| ast::UseTree::cast(n).and_then(|u| u.path()))
65}
66
67#[derive(PartialEq)]
68enum Def {
69 ModuleDef(ModuleDef),
70 MacroDef(MacroDef),
71}
72
73impl Def {
74 fn name(&self, db: &RootDatabase) -> Option<Name> {
75 match self {
76 Def::ModuleDef(def) => def.name(db),
77 Def::MacroDef(def) => def.name(db),
78 }
79 }
80}
81
82fn find_defs_in_mod(
83 ctx: &AssistContext,
84 from: SemanticsScope<'_>,
85 path: &ast::Path,
86) -> Option<Vec<Def>> {
87 let hir_path = ctx.sema.lower_path(&path)?;
88 let module = if let Some(PathResolution::Def(ModuleDef::Module(module))) =
89 from.resolve_hir_path_qualifier(&hir_path)
90 {
91 module
92 } else {
93 return None;
94 };
95
96 let module_scope = module.scope(ctx.db(), from.module());
97
98 let mut defs = vec![];
99 for (_, def) in module_scope {
100 match def {
101 ScopeDef::ModuleDef(def) => defs.push(Def::ModuleDef(def)),
102 ScopeDef::MacroDef(def) => defs.push(Def::MacroDef(def)),
103 _ => continue,
104 }
105 }
106
107 Some(defs)
108}
109
110fn find_used_names(
111 ctx: &AssistContext,
112 defs_in_mod: Vec<Def>,
113 name_refs_in_source_file: Vec<ast::NameRef>,
114) -> Vec<Name> {
115 let defs_in_source_file = name_refs_in_source_file
116 .iter()
117 .filter_map(|r| classify_name_ref(&ctx.sema, r))
118 .filter_map(|rc| match rc {
119 NameRefClass::Definition(Definition::ModuleDef(def)) => Some(Def::ModuleDef(def)),
120 NameRefClass::Definition(Definition::Macro(def)) => Some(Def::MacroDef(def)),
121 _ => None,
122 })
123 .collect::<Vec<Def>>();
124
125 defs_in_mod
126 .iter()
127 .filter(|def| {
128 if let Def::ModuleDef(ModuleDef::Trait(tr)) = def {
129 for item in tr.items(ctx.db()) {
130 if let AssocItem::Function(f) = item {
131 if defs_in_source_file.contains(&Def::ModuleDef(ModuleDef::Function(f))) {
132 return true;
133 }
134 }
135 }
136 }
137
138 defs_in_source_file.contains(def)
139 })
140 .filter_map(|d| d.name(ctx.db()))
141 .collect()
142}
143
144fn replace_ast(
145 builder: &mut AssistBuilder,
146 node: &SyntaxNode,
147 path: ast::Path,
148 used_names: Vec<Name>,
149) {
150 let replacement: Either<ast::UseTree, ast::UseTreeList> = match used_names.as_slice() {
151 [name] => Either::Left(ast::make::use_tree(
152 ast::make::path_from_text(&format!("{}::{}", path, name)),
153 None,
154 None,
155 false,
156 )),
157 names => Either::Right(ast::make::use_tree_list(names.iter().map(|n| {
158 ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false)
159 }))),
160 };
161
162 let mut replace_node = |replacement: Either<ast::UseTree, ast::UseTreeList>| {
163 algo::diff(node, &replacement.either(|u| u.syntax().clone(), |ut| ut.syntax().clone()))
164 .into_text_edit(builder.text_edit_builder());
165 };
166
167 match_ast! {
168 match node {
169 ast::UseTree(use_tree) => {
170 replace_node(replacement);
171 },
172 ast::UseTreeList(use_tree_list) => {
173 replace_node(replacement);
174 },
175 ast::Use(use_item) => {
176 builder.replace_ast(use_item, ast::make::use_(replacement.left_or_else(|ut| ast::make::use_tree(path, Some(ut), None, false))));
177 },
178 _ => {},
179 }
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use crate::tests::{check_assist, check_assist_not_applicable};
186
187 use super::*;
188
189 #[test]
190 fn expanding_glob_import() {
191 check_assist(
192 expand_glob_import,
193 r"
194mod foo {
195 pub struct Bar;
196 pub struct Baz;
197 pub struct Qux;
198
199 pub fn f() {}
200}
201
202use foo::*<|>;
203
204fn qux(bar: Bar, baz: Baz) {
205 f();
206}
207",
208 r"
209mod foo {
210 pub struct Bar;
211 pub struct Baz;
212 pub struct Qux;
213
214 pub fn f() {}
215}
216
217use foo::{Baz, Bar, f};
218
219fn qux(bar: Bar, baz: Baz) {
220 f();
221}
222",
223 )
224 }
225
226 #[test]
227 fn expanding_glob_import_with_existing_explicit_names() {
228 check_assist(
229 expand_glob_import,
230 r"
231mod foo {
232 pub struct Bar;
233 pub struct Baz;
234 pub struct Qux;
235
236 pub fn f() {}
237}
238
239use foo::{*<|>, f};
240
241fn qux(bar: Bar, baz: Baz) {
242 f();
243}
244",
245 r"
246mod foo {
247 pub struct Bar;
248 pub struct Baz;
249 pub struct Qux;
250
251 pub fn f() {}
252}
253
254use foo::{Baz, Bar, f};
255
256fn qux(bar: Bar, baz: Baz) {
257 f();
258}
259",
260 )
261 }
262
263 #[test]
264 fn expanding_nested_glob_import() {
265 check_assist(
266 expand_glob_import,
267 r"
268mod foo {
269 mod bar {
270 pub struct Bar;
271 pub struct Baz;
272 pub struct Qux;
273
274 pub fn f() {}
275 }
276
277 mod baz {
278 pub fn g() {}
279 }
280}
281
282use foo::{bar::{*<|>, f}, baz::*};
283
284fn qux(bar: Bar, baz: Baz) {
285 f();
286 g();
287}
288",
289 r"
290mod foo {
291 mod bar {
292 pub struct Bar;
293 pub struct Baz;
294 pub struct Qux;
295
296 pub fn f() {}
297 }
298
299 mod baz {
300 pub fn g() {}
301 }
302}
303
304use foo::{bar::{Baz, Bar, f}, baz::*};
305
306fn qux(bar: Bar, baz: Baz) {
307 f();
308 g();
309}
310",
311 )
312 }
313
314 #[test]
315 fn expanding_glob_import_with_macro_defs() {
316 check_assist(
317 expand_glob_import,
318 r"
319//- /lib.rs crate:foo
320#[macro_export]
321macro_rules! bar {
322 () => ()
323}
324
325pub fn baz() {}
326
327//- /main.rs crate:main deps:foo
328use foo::*<|>;
329
330fn main() {
331 bar!();
332 baz();
333}
334",
335 r"
336use foo::{bar, baz};
337
338fn main() {
339 bar!();
340 baz();
341}
342",
343 )
344 }
345
346 #[test]
347 fn expanding_glob_import_with_trait_method_uses() {
348 check_assist(
349 expand_glob_import,
350 r"
351//- /lib.rs crate:foo
352pub trait Tr {
353 fn method(&self) {}
354}
355impl Tr for () {}
356
357//- /main.rs crate:main deps:foo
358use foo::*<|>;
359
360fn main() {
361 ().method();
362}
363",
364 r"
365use foo::Tr;
366
367fn main() {
368 ().method();
369}
370",
371 )
372 }
373
374 #[test]
375 fn expanding_is_not_applicable_if_cursor_is_not_in_star_token() {
376 check_assist_not_applicable(
377 expand_glob_import,
378 r"
379 mod foo {
380 pub struct Bar;
381 pub struct Baz;
382 pub struct Qux;
383 }
384
385 use foo::Bar<|>;
386
387 fn qux(bar: Bar, baz: Baz) {}
388 ",
389 )
390 }
391}
diff --git a/crates/ra_assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ra_assists/src/handlers/extract_struct_from_enum_variant.rs
index 2b8e273b3..ccec688ca 100644
--- a/crates/ra_assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/crates/ra_assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -31,7 +31,7 @@ pub(crate) fn extract_struct_from_enum_variant(
31 acc: &mut Assists, 31 acc: &mut Assists,
32 ctx: &AssistContext, 32 ctx: &AssistContext,
33) -> Option<()> { 33) -> Option<()> {
34 let variant = ctx.find_node_at_offset::<ast::EnumVariant>()?; 34 let variant = ctx.find_node_at_offset::<ast::Variant>()?;
35 let field_list = match variant.kind() { 35 let field_list = match variant.kind() {
36 ast::StructKind::Tuple(field_list) => field_list, 36 ast::StructKind::Tuple(field_list) => field_list,
37 _ => return None, 37 _ => return None,
diff --git a/crates/ra_assists/src/handlers/extract_variable.rs b/crates/ra_assists/src/handlers/extract_variable.rs
index 098adf078..cc62db0c4 100644
--- a/crates/ra_assists/src/handlers/extract_variable.rs
+++ b/crates/ra_assists/src/handlers/extract_variable.rs
@@ -1,7 +1,7 @@
1use ra_syntax::{ 1use ra_syntax::{
2 ast::{self, AstNode}, 2 ast::{self, AstNode},
3 SyntaxKind::{ 3 SyntaxKind::{
4 BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR, 4 BLOCK_EXPR, BREAK_EXPR, CLOSURE_EXPR, COMMENT, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR,
5 }, 5 },
6 SyntaxNode, 6 SyntaxNode,
7}; 7};
@@ -45,7 +45,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option
45 target, 45 target,
46 move |edit| { 46 move |edit| {
47 let field_shorthand = 47 let field_shorthand =
48 match to_extract.syntax().parent().and_then(ast::RecordField::cast) { 48 match to_extract.syntax().parent().and_then(ast::RecordExprField::cast) {
49 Some(field) => field.name_ref(), 49 Some(field) => field.name_ref(),
50 None => None, 50 None => None,
51 }; 51 };
@@ -148,7 +148,7 @@ impl Anchor {
148 } 148 }
149 149
150 if let Some(parent) = node.parent() { 150 if let Some(parent) = node.parent() {
151 if parent.kind() == MATCH_ARM || parent.kind() == LAMBDA_EXPR { 151 if parent.kind() == MATCH_ARM || parent.kind() == CLOSURE_EXPR {
152 return Some(Anchor::WrapInBlock(node)); 152 return Some(Anchor::WrapInBlock(node));
153 } 153 }
154 } 154 }
diff --git a/crates/ra_assists/src/handlers/fill_match_arms.rs b/crates/ra_assists/src/handlers/fill_match_arms.rs
index 708e1bc6c..6698d1a27 100644
--- a/crates/ra_assists/src/handlers/fill_match_arms.rs
+++ b/crates/ra_assists/src/handlers/fill_match_arms.rs
@@ -43,7 +43,7 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
43 43
44 let mut arms: Vec<MatchArm> = match_arm_list.arms().collect(); 44 let mut arms: Vec<MatchArm> = match_arm_list.arms().collect();
45 if arms.len() == 1 { 45 if arms.len() == 1 {
46 if let Some(Pat::PlaceholderPat(..)) = arms[0].pat() { 46 if let Some(Pat::WildcardPat(..)) = arms[0].pat() {
47 arms.clear(); 47 arms.clear();
48 } 48 }
49 } 49 }
@@ -116,17 +116,15 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
116 match (first_new_arm, ctx.config.snippet_cap) { 116 match (first_new_arm, ctx.config.snippet_cap) {
117 (Some(first_new_arm), Some(cap)) => { 117 (Some(first_new_arm), Some(cap)) => {
118 let extend_lifetime; 118 let extend_lifetime;
119 let cursor = match first_new_arm 119 let cursor =
120 .syntax() 120 match first_new_arm.syntax().descendants().find_map(ast::WildcardPat::cast)
121 .descendants() 121 {
122 .find_map(ast::PlaceholderPat::cast) 122 Some(it) => {
123 { 123 extend_lifetime = it.syntax().clone();
124 Some(it) => { 124 Cursor::Replace(&extend_lifetime)
125 extend_lifetime = it.syntax().clone(); 125 }
126 Cursor::Replace(&extend_lifetime) 126 None => Cursor::Before(first_new_arm.syntax()),
127 } 127 };
128 None => Cursor::Before(first_new_arm.syntax()),
129 };
130 let snippet = render_snippet(cap, new_arm_list.syntax(), cursor); 128 let snippet = render_snippet(cap, new_arm_list.syntax(), cursor);
131 builder.replace_snippet(cap, old_range, snippet); 129 builder.replace_snippet(cap, old_range, snippet);
132 } 130 }
@@ -152,7 +150,7 @@ fn does_pat_match_variant(pat: &Pat, var: &Pat) -> bool {
152 let first_node_text = |pat: &Pat| pat.syntax().first_child().map(|node| node.text()); 150 let first_node_text = |pat: &Pat| pat.syntax().first_child().map(|node| node.text());
153 151
154 let pat_head = match pat { 152 let pat_head = match pat {
155 Pat::BindPat(bind_pat) => { 153 Pat::IdentPat(bind_pat) => {
156 if let Some(p) = bind_pat.pat() { 154 if let Some(p) = bind_pat.pat() {
157 first_node_text(&p) 155 first_node_text(&p)
158 } else { 156 } else {
@@ -199,12 +197,11 @@ fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> O
199 // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though 197 // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
200 let pat: ast::Pat = match var.source(db).value.kind() { 198 let pat: ast::Pat = match var.source(db).value.kind() {
201 ast::StructKind::Tuple(field_list) => { 199 ast::StructKind::Tuple(field_list) => {
202 let pats = 200 let pats = iter::repeat(make::wildcard_pat().into()).take(field_list.fields().count());
203 iter::repeat(make::placeholder_pat().into()).take(field_list.fields().count());
204 make::tuple_struct_pat(path, pats).into() 201 make::tuple_struct_pat(path, pats).into()
205 } 202 }
206 ast::StructKind::Record(field_list) => { 203 ast::StructKind::Record(field_list) => {
207 let pats = field_list.fields().map(|f| make::bind_pat(f.name().unwrap()).into()); 204 let pats = field_list.fields().map(|f| make::ident_pat(f.name().unwrap()).into());
208 make::record_pat(path, pats).into() 205 make::record_pat(path, pats).into()
209 } 206 }
210 ast::StructKind::Unit => make::path_pat(path), 207 ast::StructKind::Unit => make::path_pat(path),
diff --git a/crates/ra_assists/src/handlers/fix_visibility.rs b/crates/ra_assists/src/handlers/fix_visibility.rs
index 1d3ed3c6a..1aefa79cc 100644
--- a/crates/ra_assists/src/handlers/fix_visibility.rs
+++ b/crates/ra_assists/src/handlers/fix_visibility.rs
@@ -82,7 +82,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> O
82} 82}
83 83
84fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 84fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
85 let record_field: ast::RecordField = ctx.find_node_at_offset()?; 85 let record_field: ast::RecordExprField = ctx.find_node_at_offset()?;
86 let (record_field_def, _) = ctx.sema.resolve_record_field(&record_field)?; 86 let (record_field_def, _) = ctx.sema.resolve_record_field(&record_field)?;
87 87
88 let current_module = ctx.sema.scope(record_field.syntax()).module()?; 88 let current_module = ctx.sema.scope(record_field.syntax()).module()?;
diff --git a/crates/ra_assists/src/handlers/generate_derive.rs b/crates/ra_assists/src/handlers/generate_derive.rs
index 6ccf39900..90ece9fab 100644
--- a/crates/ra_assists/src/handlers/generate_derive.rs
+++ b/crates/ra_assists/src/handlers/generate_derive.rs
@@ -26,7 +26,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
26// ``` 26// ```
27pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 27pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
28 let cap = ctx.config.snippet_cap?; 28 let cap = ctx.config.snippet_cap?;
29 let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?; 29 let nominal = ctx.find_node_at_offset::<ast::AdtDef>()?;
30 let node_start = derive_insertion_offset(&nominal)?; 30 let node_start = derive_insertion_offset(&nominal)?;
31 let target = nominal.syntax().text_range(); 31 let target = nominal.syntax().text_range();
32 acc.add( 32 acc.add(
@@ -58,7 +58,7 @@ pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<
58} 58}
59 59
60// Insert `derive` after doc comments. 60// Insert `derive` after doc comments.
61fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextSize> { 61fn derive_insertion_offset(nominal: &ast::AdtDef) -> Option<TextSize> {
62 let non_ws_child = nominal 62 let non_ws_child = nominal
63 .syntax() 63 .syntax()
64 .children_with_tokens() 64 .children_with_tokens()
diff --git a/crates/ra_assists/src/handlers/generate_from_impl_for_enum.rs b/crates/ra_assists/src/handlers/generate_from_impl_for_enum.rs
index a347e3c2e..4c1aef8a2 100644
--- a/crates/ra_assists/src/handlers/generate_from_impl_for_enum.rs
+++ b/crates/ra_assists/src/handlers/generate_from_impl_for_enum.rs
@@ -22,7 +22,7 @@ use crate::{utils::FamousDefs, AssistContext, AssistId, AssistKind, Assists};
22// } 22// }
23// ``` 23// ```
24pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 24pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
25 let variant = ctx.find_node_at_offset::<ast::EnumVariant>()?; 25 let variant = ctx.find_node_at_offset::<ast::Variant>()?;
26 let variant_name = variant.name()?; 26 let variant_name = variant.name()?;
27 let enum_name = variant.parent_enum().name()?; 27 let enum_name = variant.parent_enum().name()?;
28 let field_list = match variant.kind() { 28 let field_list = match variant.kind() {
@@ -32,9 +32,9 @@ pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext
32 if field_list.fields().count() != 1 { 32 if field_list.fields().count() != 1 {
33 return None; 33 return None;
34 } 34 }
35 let field_type = field_list.fields().next()?.type_ref()?; 35 let field_type = field_list.fields().next()?.ty()?;
36 let path = match field_type { 36 let path = match field_type {
37 ast::TypeRef::PathType(it) => it, 37 ast::Type::PathType(it) => it,
38 _ => return None, 38 _ => return None,
39 }; 39 };
40 40
@@ -69,7 +69,7 @@ impl From<{0}> for {1} {{
69 69
70fn existing_from_impl( 70fn existing_from_impl(
71 sema: &'_ hir::Semantics<'_, RootDatabase>, 71 sema: &'_ hir::Semantics<'_, RootDatabase>,
72 variant: &ast::EnumVariant, 72 variant: &ast::Variant,
73) -> Option<()> { 73) -> Option<()> {
74 let variant = sema.to_def(variant)?; 74 let variant = sema.to_def(variant)?;
75 let enum_ = variant.parent_enum(sema.db); 75 let enum_ = variant.parent_enum(sema.db);
diff --git a/crates/ra_assists/src/handlers/generate_function.rs b/crates/ra_assists/src/handlers/generate_function.rs
index b721b96bb..acc97e648 100644
--- a/crates/ra_assists/src/handlers/generate_function.rs
+++ b/crates/ra_assists/src/handlers/generate_function.rs
@@ -82,7 +82,7 @@ struct FunctionTemplate {
82 insert_offset: TextSize, 82 insert_offset: TextSize,
83 placeholder_expr: ast::MacroCall, 83 placeholder_expr: ast::MacroCall,
84 leading_ws: String, 84 leading_ws: String,
85 fn_def: ast::FnDef, 85 fn_def: ast::Fn,
86 trailing_ws: String, 86 trailing_ws: String,
87 file: FileId, 87 file: FileId,
88} 88}
@@ -104,7 +104,7 @@ impl FunctionTemplate {
104struct FunctionBuilder { 104struct FunctionBuilder {
105 target: GeneratedFunctionTarget, 105 target: GeneratedFunctionTarget,
106 fn_name: ast::Name, 106 fn_name: ast::Name,
107 type_params: Option<ast::TypeParamList>, 107 type_params: Option<ast::GenericParamList>,
108 params: ast::ParamList, 108 params: ast::ParamList,
109 file: FileId, 109 file: FileId,
110 needs_pub: bool, 110 needs_pub: bool,
@@ -142,7 +142,7 @@ impl FunctionBuilder {
142 let fn_body = make::block_expr(vec![], Some(placeholder_expr)); 142 let fn_body = make::block_expr(vec![], Some(placeholder_expr));
143 let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None }; 143 let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None };
144 let mut fn_def = 144 let mut fn_def =
145 make::fn_def(visibility, self.fn_name, self.type_params, self.params, fn_body); 145 make::fn_(visibility, self.fn_name, self.type_params, self.params, fn_body);
146 let leading_ws; 146 let leading_ws;
147 let trailing_ws; 147 let trailing_ws;
148 148
@@ -200,7 +200,7 @@ fn fn_args(
200 ctx: &AssistContext, 200 ctx: &AssistContext,
201 target_module: hir::Module, 201 target_module: hir::Module,
202 call: &ast::CallExpr, 202 call: &ast::CallExpr,
203) -> Option<(Option<ast::TypeParamList>, ast::ParamList)> { 203) -> Option<(Option<ast::GenericParamList>, ast::ParamList)> {
204 let mut arg_names = Vec::new(); 204 let mut arg_names = Vec::new();
205 let mut arg_types = Vec::new(); 205 let mut arg_types = Vec::new();
206 for arg in call.arg_list()?.args() { 206 for arg in call.arg_list()?.args() {
diff --git a/crates/ra_assists/src/handlers/generate_impl.rs b/crates/ra_assists/src/handlers/generate_impl.rs
index cbbac1d7f..d9b87c9c0 100644
--- a/crates/ra_assists/src/handlers/generate_impl.rs
+++ b/crates/ra_assists/src/handlers/generate_impl.rs
@@ -1,4 +1,4 @@
1use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; 1use ra_syntax::ast::{self, AstNode, GenericParamsOwner, NameOwner};
2use stdx::{format_to, SepBy}; 2use stdx::{format_to, SepBy};
3 3
4use crate::{AssistContext, AssistId, AssistKind, Assists}; 4use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -23,7 +23,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
23// } 23// }
24// ``` 24// ```
25pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 25pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
26 let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?; 26 let nominal = ctx.find_node_at_offset::<ast::AdtDef>()?;
27 let name = nominal.name()?; 27 let name = nominal.name()?;
28 let target = nominal.syntax().text_range(); 28 let target = nominal.syntax().text_range();
29 acc.add( 29 acc.add(
@@ -31,7 +31,7 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()
31 format!("Generate impl for `{}`", name), 31 format!("Generate impl for `{}`", name),
32 target, 32 target,
33 |edit| { 33 |edit| {
34 let type_params = nominal.type_param_list(); 34 let type_params = nominal.generic_param_list();
35 let start_offset = nominal.syntax().text_range().end(); 35 let start_offset = nominal.syntax().text_range().end();
36 let mut buf = String::new(); 36 let mut buf = String::new();
37 buf.push_str("\n\nimpl"); 37 buf.push_str("\n\nimpl");
diff --git a/crates/ra_assists/src/handlers/generate_new.rs b/crates/ra_assists/src/handlers/generate_new.rs
index e27def1d8..b84aa24b6 100644
--- a/crates/ra_assists/src/handlers/generate_new.rs
+++ b/crates/ra_assists/src/handlers/generate_new.rs
@@ -1,8 +1,6 @@
1use hir::Adt; 1use hir::Adt;
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{ 3 ast::{self, AstNode, GenericParamsOwner, NameOwner, StructKind, VisibilityOwner},
4 self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner,
5 },
6 T, 4 T,
7}; 5};
8use stdx::{format_to, SepBy}; 6use stdx::{format_to, SepBy};
@@ -30,7 +28,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
30// 28//
31// ``` 29// ```
32pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 30pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
33 let strukt = ctx.find_node_at_offset::<ast::StructDef>()?; 31 let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
34 32
35 // We want to only apply this to non-union structs with named fields 33 // We want to only apply this to non-union structs with named fields
36 let field_list = match strukt.kind() { 34 let field_list = match strukt.kind() {
@@ -53,9 +51,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
53 51
54 let params = field_list 52 let params = field_list
55 .fields() 53 .fields()
56 .filter_map(|f| { 54 .filter_map(|f| Some(format!("{}: {}", f.name()?.syntax(), f.ty()?.syntax())))
57 Some(format!("{}: {}", f.name()?.syntax(), f.ascribed_type()?.syntax()))
58 })
59 .sep_by(", "); 55 .sep_by(", ");
60 let fields = field_list.fields().filter_map(|f| f.name()).sep_by(", "); 56 let fields = field_list.fields().filter_map(|f| f.name()).sep_by(", ");
61 57
@@ -90,8 +86,8 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
90 86
91// Generates the surrounding `impl Type { <code> }` including type and lifetime 87// Generates the surrounding `impl Type { <code> }` including type and lifetime
92// parameters 88// parameters
93fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String { 89fn generate_impl_text(strukt: &ast::Struct, code: &str) -> String {
94 let type_params = strukt.type_param_list(); 90 let type_params = strukt.generic_param_list();
95 let mut buf = String::with_capacity(code.len()); 91 let mut buf = String::with_capacity(code.len());
96 buf.push_str("\n\nimpl"); 92 buf.push_str("\n\nimpl");
97 if let Some(type_params) = &type_params { 93 if let Some(type_params) = &type_params {
@@ -121,7 +117,7 @@ fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String {
121// 117//
122// FIXME: change the new fn checking to a more semantic approach when that's more 118// FIXME: change the new fn checking to a more semantic approach when that's more
123// viable (e.g. we process proc macros, etc) 119// viable (e.g. we process proc macros, etc)
124fn find_struct_impl(ctx: &AssistContext, strukt: &ast::StructDef) -> Option<Option<ast::ImplDef>> { 120fn find_struct_impl(ctx: &AssistContext, strukt: &ast::Struct) -> Option<Option<ast::Impl>> {
125 let db = ctx.db(); 121 let db = ctx.db();
126 let module = strukt.syntax().ancestors().find(|node| { 122 let module = strukt.syntax().ancestors().find(|node| {
127 ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind()) 123 ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind())
@@ -129,7 +125,7 @@ fn find_struct_impl(ctx: &AssistContext, strukt: &ast::StructDef) -> Option<Opti
129 125
130 let struct_def = ctx.sema.to_def(strukt)?; 126 let struct_def = ctx.sema.to_def(strukt)?;
131 127
132 let block = module.descendants().filter_map(ast::ImplDef::cast).find_map(|impl_blk| { 128 let block = module.descendants().filter_map(ast::Impl::cast).find_map(|impl_blk| {
133 let blk = ctx.sema.to_def(&impl_blk)?; 129 let blk = ctx.sema.to_def(&impl_blk)?;
134 130
135 // FIXME: handle e.g. `struct S<T>; impl<U> S<U> {}` 131 // FIXME: handle e.g. `struct S<T>; impl<U> S<U> {}`
@@ -157,10 +153,10 @@ fn find_struct_impl(ctx: &AssistContext, strukt: &ast::StructDef) -> Option<Opti
157 Some(block) 153 Some(block)
158} 154}
159 155
160fn has_new_fn(imp: &ast::ImplDef) -> bool { 156fn has_new_fn(imp: &ast::Impl) -> bool {
161 if let Some(il) = imp.item_list() { 157 if let Some(il) = imp.assoc_item_list() {
162 for item in il.assoc_items() { 158 for item in il.assoc_items() {
163 if let ast::AssocItem::FnDef(f) = item { 159 if let ast::AssocItem::Fn(f) = item {
164 if let Some(name) = f.name() { 160 if let Some(name) = f.name() {
165 if name.text().eq_ignore_ascii_case("new") { 161 if name.text().eq_ignore_ascii_case("new") {
166 return true; 162 return true;
diff --git a/crates/ra_assists/src/handlers/inline_local_variable.rs b/crates/ra_assists/src/handlers/inline_local_variable.rs
index 2fdfabaf5..3c58020f8 100644
--- a/crates/ra_assists/src/handlers/inline_local_variable.rs
+++ b/crates/ra_assists/src/handlers/inline_local_variable.rs
@@ -29,7 +29,7 @@ use crate::{
29pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 29pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
30 let let_stmt = ctx.find_node_at_offset::<ast::LetStmt>()?; 30 let let_stmt = ctx.find_node_at_offset::<ast::LetStmt>()?;
31 let bind_pat = match let_stmt.pat()? { 31 let bind_pat = match let_stmt.pat()? {
32 ast::Pat::BindPat(pat) => pat, 32 ast::Pat::IdentPat(pat) => pat,
33 _ => return None, 33 _ => return None,
34 }; 34 };
35 if bind_pat.mut_token().is_some() { 35 if bind_pat.mut_token().is_some() {
diff --git a/crates/ra_assists/src/handlers/introduce_named_lifetime.rs b/crates/ra_assists/src/handlers/introduce_named_lifetime.rs
index 967593031..fbaf3c06b 100644
--- a/crates/ra_assists/src/handlers/introduce_named_lifetime.rs
+++ b/crates/ra_assists/src/handlers/introduce_named_lifetime.rs
@@ -1,5 +1,5 @@
1use ra_syntax::{ 1use ra_syntax::{
2 ast::{self, NameOwner, TypeAscriptionOwner, TypeParamsOwner}, 2 ast::{self, GenericParamsOwner, NameOwner},
3 AstNode, SyntaxKind, TextRange, TextSize, 3 AstNode, SyntaxKind, TextRange, TextSize,
4}; 4};
5use rustc_hash::FxHashSet; 5use rustc_hash::FxHashSet;
@@ -38,9 +38,9 @@ pub(crate) fn introduce_named_lifetime(acc: &mut Assists, ctx: &AssistContext) -
38 let lifetime_token = ctx 38 let lifetime_token = ctx
39 .find_token_at_offset(SyntaxKind::LIFETIME) 39 .find_token_at_offset(SyntaxKind::LIFETIME)
40 .filter(|lifetime| lifetime.text() == "'_")?; 40 .filter(|lifetime| lifetime.text() == "'_")?;
41 if let Some(fn_def) = lifetime_token.ancestors().find_map(ast::FnDef::cast) { 41 if let Some(fn_def) = lifetime_token.ancestors().find_map(ast::Fn::cast) {
42 generate_fn_def_assist(acc, &fn_def, lifetime_token.text_range()) 42 generate_fn_def_assist(acc, &fn_def, lifetime_token.text_range())
43 } else if let Some(impl_def) = lifetime_token.ancestors().find_map(ast::ImplDef::cast) { 43 } else if let Some(impl_def) = lifetime_token.ancestors().find_map(ast::Impl::cast) {
44 generate_impl_def_assist(acc, &impl_def, lifetime_token.text_range()) 44 generate_impl_def_assist(acc, &impl_def, lifetime_token.text_range())
45 } else { 45 } else {
46 None 46 None
@@ -50,11 +50,11 @@ pub(crate) fn introduce_named_lifetime(acc: &mut Assists, ctx: &AssistContext) -
50/// Generate the assist for the fn def case 50/// Generate the assist for the fn def case
51fn generate_fn_def_assist( 51fn generate_fn_def_assist(
52 acc: &mut Assists, 52 acc: &mut Assists,
53 fn_def: &ast::FnDef, 53 fn_def: &ast::Fn,
54 lifetime_loc: TextRange, 54 lifetime_loc: TextRange,
55) -> Option<()> { 55) -> Option<()> {
56 let param_list: ast::ParamList = fn_def.param_list()?; 56 let param_list: ast::ParamList = fn_def.param_list()?;
57 let new_lifetime_param = generate_unique_lifetime_param_name(&fn_def.type_param_list())?; 57 let new_lifetime_param = generate_unique_lifetime_param_name(&fn_def.generic_param_list())?;
58 let end_of_fn_ident = fn_def.name()?.ident_token()?.text_range().end(); 58 let end_of_fn_ident = fn_def.name()?.ident_token()?.text_range().end();
59 let self_param = 59 let self_param =
60 // use the self if it's a reference and has no explicit lifetime 60 // use the self if it's a reference and has no explicit lifetime
@@ -67,8 +67,8 @@ fn generate_fn_def_assist(
67 // otherwise, if there's a single reference parameter without a named liftime, use that 67 // otherwise, if there's a single reference parameter without a named liftime, use that
68 let fn_params_without_lifetime: Vec<_> = param_list 68 let fn_params_without_lifetime: Vec<_> = param_list
69 .params() 69 .params()
70 .filter_map(|param| match param.ascribed_type() { 70 .filter_map(|param| match param.ty() {
71 Some(ast::TypeRef::ReferenceType(ascribed_type)) 71 Some(ast::Type::RefType(ascribed_type))
72 if ascribed_type.lifetime_token() == None => 72 if ascribed_type.lifetime_token() == None =>
73 { 73 {
74 Some(ascribed_type.amp_token()?.text_range().end()) 74 Some(ascribed_type.amp_token()?.text_range().end())
@@ -93,10 +93,10 @@ fn generate_fn_def_assist(
93/// Generate the assist for the impl def case 93/// Generate the assist for the impl def case
94fn generate_impl_def_assist( 94fn generate_impl_def_assist(
95 acc: &mut Assists, 95 acc: &mut Assists,
96 impl_def: &ast::ImplDef, 96 impl_def: &ast::Impl,
97 lifetime_loc: TextRange, 97 lifetime_loc: TextRange,
98) -> Option<()> { 98) -> Option<()> {
99 let new_lifetime_param = generate_unique_lifetime_param_name(&impl_def.type_param_list())?; 99 let new_lifetime_param = generate_unique_lifetime_param_name(&impl_def.generic_param_list())?;
100 let end_of_impl_kw = impl_def.impl_token()?.text_range().end(); 100 let end_of_impl_kw = impl_def.impl_token()?.text_range().end();
101 acc.add(AssistId(ASSIST_NAME, AssistKind::Refactor), ASSIST_LABEL, lifetime_loc, |builder| { 101 acc.add(AssistId(ASSIST_NAME, AssistKind::Refactor), ASSIST_LABEL, lifetime_loc, |builder| {
102 add_lifetime_param(impl_def, builder, end_of_impl_kw, new_lifetime_param); 102 add_lifetime_param(impl_def, builder, end_of_impl_kw, new_lifetime_param);
@@ -107,7 +107,7 @@ fn generate_impl_def_assist(
107/// Given a type parameter list, generate a unique lifetime parameter name 107/// Given a type parameter list, generate a unique lifetime parameter name
108/// which is not in the list 108/// which is not in the list
109fn generate_unique_lifetime_param_name( 109fn generate_unique_lifetime_param_name(
110 existing_type_param_list: &Option<ast::TypeParamList>, 110 existing_type_param_list: &Option<ast::GenericParamList>,
111) -> Option<char> { 111) -> Option<char> {
112 match existing_type_param_list { 112 match existing_type_param_list {
113 Some(type_params) => { 113 Some(type_params) => {
@@ -123,13 +123,13 @@ fn generate_unique_lifetime_param_name(
123 123
124/// Add the lifetime param to `builder`. If there are type parameters in `type_params_owner`, add it to the end. Otherwise 124/// Add the lifetime param to `builder`. If there are type parameters in `type_params_owner`, add it to the end. Otherwise
125/// add new type params brackets with the lifetime parameter at `new_type_params_loc`. 125/// add new type params brackets with the lifetime parameter at `new_type_params_loc`.
126fn add_lifetime_param<TypeParamsOwner: ast::TypeParamsOwner>( 126fn add_lifetime_param<TypeParamsOwner: ast::GenericParamsOwner>(
127 type_params_owner: &TypeParamsOwner, 127 type_params_owner: &TypeParamsOwner,
128 builder: &mut AssistBuilder, 128 builder: &mut AssistBuilder,
129 new_type_params_loc: TextSize, 129 new_type_params_loc: TextSize,
130 new_lifetime_param: char, 130 new_lifetime_param: char,
131) { 131) {
132 match type_params_owner.type_param_list() { 132 match type_params_owner.generic_param_list() {
133 // add the new lifetime parameter to an existing type param list 133 // add the new lifetime parameter to an existing type param list
134 Some(type_params) => { 134 Some(type_params) => {
135 builder.insert( 135 builder.insert(
diff --git a/crates/ra_assists/src/handlers/merge_imports.rs b/crates/ra_assists/src/handlers/merge_imports.rs
index 1beccb61c..c775fe25c 100644
--- a/crates/ra_assists/src/handlers/merge_imports.rs
+++ b/crates/ra_assists/src/handlers/merge_imports.rs
@@ -28,7 +28,7 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()
28 let mut rewriter = SyntaxRewriter::default(); 28 let mut rewriter = SyntaxRewriter::default();
29 let mut offset = ctx.offset(); 29 let mut offset = ctx.offset();
30 30
31 if let Some(use_item) = tree.syntax().parent().and_then(ast::UseItem::cast) { 31 if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) {
32 let (merged, to_delete) = next_prev() 32 let (merged, to_delete) = next_prev()
33 .filter_map(|dir| neighbor(&use_item, dir)) 33 .filter_map(|dir| neighbor(&use_item, dir))
34 .filter_map(|it| Some((it.clone(), it.use_tree()?))) 34 .filter_map(|it| Some((it.clone(), it.use_tree()?)))
diff --git a/crates/ra_assists/src/handlers/merge_match_arms.rs b/crates/ra_assists/src/handlers/merge_match_arms.rs
index 186a1f618..563292282 100644
--- a/crates/ra_assists/src/handlers/merge_match_arms.rs
+++ b/crates/ra_assists/src/handlers/merge_match_arms.rs
@@ -86,7 +86,7 @@ pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option
86} 86}
87 87
88fn contains_placeholder(a: &ast::MatchArm) -> bool { 88fn contains_placeholder(a: &ast::MatchArm) -> bool {
89 matches!(a.pat(), Some(ast::Pat::PlaceholderPat(..))) 89 matches!(a.pat(), Some(ast::Pat::WildcardPat(..)))
90} 90}
91 91
92#[cfg(test)] 92#[cfg(test)]
diff --git a/crates/ra_assists/src/handlers/move_bounds.rs b/crates/ra_assists/src/handlers/move_bounds.rs
index ba3dafb99..6d394443e 100644
--- a/crates/ra_assists/src/handlers/move_bounds.rs
+++ b/crates/ra_assists/src/handlers/move_bounds.rs
@@ -23,7 +23,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
23// } 23// }
24// ``` 24// ```
25pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 25pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
26 let type_param_list = ctx.find_node_at_offset::<ast::TypeParamList>()?; 26 let type_param_list = ctx.find_node_at_offset::<ast::GenericParamList>()?;
27 27
28 let mut type_params = type_param_list.type_params(); 28 let mut type_params = type_param_list.type_params();
29 if type_params.all(|p| p.type_bound_list().is_none()) { 29 if type_params.all(|p| p.type_bound_list().is_none()) {
@@ -37,13 +37,13 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext
37 37
38 let anchor = match_ast! { 38 let anchor = match_ast! {
39 match parent { 39 match parent {
40 ast::FnDef(it) => it.body()?.syntax().clone().into(), 40 ast::Fn(it) => it.body()?.syntax().clone().into(),
41 ast::TraitDef(it) => it.item_list()?.syntax().clone().into(), 41 ast::Trait(it) => it.assoc_item_list()?.syntax().clone().into(),
42 ast::ImplDef(it) => it.item_list()?.syntax().clone().into(), 42 ast::Impl(it) => it.assoc_item_list()?.syntax().clone().into(),
43 ast::EnumDef(it) => it.variant_list()?.syntax().clone().into(), 43 ast::Enum(it) => it.variant_list()?.syntax().clone().into(),
44 ast::StructDef(it) => { 44 ast::Struct(it) => {
45 it.syntax().children_with_tokens() 45 it.syntax().children_with_tokens()
46 .find(|it| it.kind() == RECORD_FIELD_DEF_LIST || it.kind() == T![;])? 46 .find(|it| it.kind() == RECORD_FIELD_LIST || it.kind() == T![;])?
47 }, 47 },
48 _ => return None 48 _ => return None
49 } 49 }
diff --git a/crates/ra_assists/src/handlers/raw_string.rs b/crates/ra_assists/src/handlers/raw_string.rs
index 4e8a0c2db..4c797178f 100644
--- a/crates/ra_assists/src/handlers/raw_string.rs
+++ b/crates/ra_assists/src/handlers/raw_string.rs
@@ -173,7 +173,7 @@ fn test_required_hashes() {
173} 173}
174 174
175#[cfg(test)] 175#[cfg(test)]
176mod test { 176mod tests {
177 use test_utils::mark; 177 use test_utils::mark;
178 178
179 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target}; 179 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
diff --git a/crates/ra_assists/src/handlers/remove_dbg.rs b/crates/ra_assists/src/handlers/remove_dbg.rs
index a616cca57..9430ce1b5 100644
--- a/crates/ra_assists/src/handlers/remove_dbg.rs
+++ b/crates/ra_assists/src/handlers/remove_dbg.rs
@@ -1,6 +1,6 @@
1use ra_syntax::{ 1use ra_syntax::{
2 ast::{self, AstNode}, 2 ast::{self, AstNode},
3 TextSize, T, 3 TextRange, TextSize, T,
4}; 4};
5 5
6use crate::{AssistContext, AssistId, AssistKind, Assists}; 6use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -27,19 +27,33 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
27 return None; 27 return None;
28 } 28 }
29 29
30 let macro_range = macro_call.syntax().text_range(); 30 let is_leaf = macro_call.syntax().next_sibling().is_none();
31 31
32 let macro_content = { 32 let macro_end = if macro_call.semicolon_token().is_some() {
33 let macro_args = macro_call.token_tree()?.syntax().clone(); 33 macro_call.syntax().text_range().end() - TextSize::of(';')
34 } else {
35 macro_call.syntax().text_range().end()
36 };
34 37
35 let text = macro_args.text(); 38 // macro_range determines what will be deleted and replaced with macro_content
36 let without_parens = TextSize::of('(')..text.len() - TextSize::of(')'); 39 let macro_range = TextRange::new(macro_call.syntax().text_range().start(), macro_end);
37 text.slice(without_parens).to_string() 40 let paste_instead_of_dbg = {
41 let text = macro_call.token_tree()?.syntax().text();
42
43 // leafiness determines if we should include the parenthesis or not
44 let slice_index: TextRange = if is_leaf {
45 // leaf means - we can extract the contents of the dbg! in text
46 TextRange::new(TextSize::of('('), text.len() - TextSize::of(')'))
47 } else {
48 // not leaf - means we should keep the parens
49 TextRange::up_to(text.len())
50 };
51 text.slice(slice_index).to_string()
38 }; 52 };
39 53
40 let target = macro_call.syntax().text_range(); 54 let target = macro_call.syntax().text_range();
41 acc.add(AssistId("remove_dbg", AssistKind::Refactor), "Remove dbg!()", target, |builder| { 55 acc.add(AssistId("remove_dbg", AssistKind::Refactor), "Remove dbg!()", target, |builder| {
42 builder.replace(macro_range, macro_content); 56 builder.replace(macro_range, paste_instead_of_dbg);
43 }) 57 })
44} 58}
45 59
@@ -99,6 +113,7 @@ fn foo(n: usize) {
99", 113",
100 ); 114 );
101 } 115 }
116
102 #[test] 117 #[test]
103 fn test_remove_dbg_with_brackets_and_braces() { 118 fn test_remove_dbg_with_brackets_and_braces() {
104 check_assist(remove_dbg, "dbg![<|>1 + 1]", "1 + 1"); 119 check_assist(remove_dbg, "dbg![<|>1 + 1]", "1 + 1");
@@ -113,7 +128,7 @@ fn foo(n: usize) {
113 } 128 }
114 129
115 #[test] 130 #[test]
116 fn remove_dbg_target() { 131 fn test_remove_dbg_target() {
117 check_assist_target( 132 check_assist_target(
118 remove_dbg, 133 remove_dbg,
119 " 134 "
@@ -126,4 +141,65 @@ fn foo(n: usize) {
126 "dbg!(n.checked_sub(4))", 141 "dbg!(n.checked_sub(4))",
127 ); 142 );
128 } 143 }
144
145 #[test]
146 fn test_remove_dbg_keep_semicolon() {
147 // https://github.com/rust-analyzer/rust-analyzer/issues/5129#issuecomment-651399779
148 // not quite though
149 // adding a comment at the end of the line makes
150 // the ast::MacroCall to include the semicolon at the end
151 check_assist(
152 remove_dbg,
153 r#"let res = <|>dbg!(1 * 20); // needless comment"#,
154 r#"let res = 1 * 20; // needless comment"#,
155 );
156 }
157
158 #[test]
159 fn test_remove_dbg_keep_expression() {
160 check_assist(
161 remove_dbg,
162 r#"let res = <|>dbg!(a + b).foo();"#,
163 r#"let res = (a + b).foo();"#,
164 );
165 }
166
167 #[test]
168 fn test_remove_dbg_from_inside_fn() {
169 check_assist_target(
170 remove_dbg,
171 r#"
172fn square(x: u32) -> u32 {
173 x * x
174}
175
176fn main() {
177 let x = square(dbg<|>!(5 + 10));
178 println!("{}", x);
179}"#,
180 "dbg!(5 + 10)",
181 );
182
183 check_assist(
184 remove_dbg,
185 r#"
186fn square(x: u32) -> u32 {
187 x * x
188}
189
190fn main() {
191 let x = square(dbg<|>!(5 + 10));
192 println!("{}", x);
193}"#,
194 r#"
195fn square(x: u32) -> u32 {
196 x * x
197}
198
199fn main() {
200 let x = square(5 + 10);
201 println!("{}", x);
202}"#,
203 );
204 }
129} 205}
diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs
index 2ac1c56cf..c9b743a06 100644
--- a/crates/ra_assists/src/handlers/reorder_fields.rs
+++ b/crates/ra_assists/src/handlers/reorder_fields.rs
@@ -23,7 +23,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
23// ``` 23// ```
24// 24//
25pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 25pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
26 reorder::<ast::RecordLit>(acc, ctx).or_else(|| reorder::<ast::RecordPat>(acc, ctx)) 26 reorder::<ast::RecordExpr>(acc, ctx).or_else(|| reorder::<ast::RecordPat>(acc, ctx))
27} 27}
28 28
29fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 29fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
@@ -56,8 +56,8 @@ fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
56 56
57fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> { 57fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> {
58 match node.kind() { 58 match node.kind() {
59 RECORD_LIT => vec![RECORD_FIELD], 59 RECORD_EXPR => vec![RECORD_EXPR_FIELD],
60 RECORD_PAT => vec![RECORD_FIELD_PAT, BIND_PAT], 60 RECORD_PAT => vec![RECORD_PAT_FIELD, IDENT_PAT],
61 _ => vec![], 61 _ => vec![],
62 } 62 }
63} 63}
@@ -65,8 +65,8 @@ fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> {
65fn get_field_name(node: &SyntaxNode) -> String { 65fn get_field_name(node: &SyntaxNode) -> String {
66 let res = match_ast! { 66 let res = match_ast! {
67 match node { 67 match node {
68 ast::RecordField(field) => field.field_name().map(|it| it.to_string()), 68 ast::RecordExprField(field) => field.field_name().map(|it| it.to_string()),
69 ast::RecordFieldPat(field) => field.field_name().map(|it| it.to_string()), 69 ast::RecordPatField(field) => field.field_name().map(|it| it.to_string()),
70 _ => None, 70 _ => None,
71 } 71 }
72 }; 72 };
diff --git a/crates/ra_assists/src/handlers/replace_if_let_with_match.rs b/crates/ra_assists/src/handlers/replace_if_let_with_match.rs
index b7e30a7f2..ecafb74a1 100644
--- a/crates/ra_assists/src/handlers/replace_if_let_with_match.rs
+++ b/crates/ra_assists/src/handlers/replace_if_let_with_match.rs
@@ -65,7 +65,7 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext)
65 .type_of_pat(&pat) 65 .type_of_pat(&pat)
66 .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty)) 66 .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty))
67 .map(|it| it.sad_pattern()) 67 .map(|it| it.sad_pattern())
68 .unwrap_or_else(|| make::placeholder_pat().into()); 68 .unwrap_or_else(|| make::wildcard_pat().into());
69 let else_expr = unwrap_trivial_block(else_block); 69 let else_expr = unwrap_trivial_block(else_block);
70 make::match_arm(vec![pattern], else_expr) 70 make::match_arm(vec![pattern], else_expr)
71 }; 71 };
diff --git a/crates/ra_assists/src/handlers/replace_let_with_if_let.rs b/crates/ra_assists/src/handlers/replace_let_with_if_let.rs
index a49292c97..e4d436dec 100644
--- a/crates/ra_assists/src/handlers/replace_let_with_if_let.rs
+++ b/crates/ra_assists/src/handlers/replace_let_with_if_let.rs
@@ -50,10 +50,10 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) ->
50 target, 50 target,
51 |edit| { 51 |edit| {
52 let with_placeholder: ast::Pat = match happy_variant { 52 let with_placeholder: ast::Pat = match happy_variant {
53 None => make::placeholder_pat().into(), 53 None => make::wildcard_pat().into(),
54 Some(var_name) => make::tuple_struct_pat( 54 Some(var_name) => make::tuple_struct_pat(
55 make::path_unqualified(make::path_segment(make::name_ref(var_name))), 55 make::path_unqualified(make::path_segment(make::name_ref(var_name))),
56 once(make::placeholder_pat().into()), 56 once(make::wildcard_pat().into()),
57 ) 57 )
58 .into(), 58 .into(),
59 }; 59 };
@@ -62,8 +62,7 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) ->
62 let if_ = make::expr_if(make::condition(init, Some(with_placeholder)), block); 62 let if_ = make::expr_if(make::condition(init, Some(with_placeholder)), block);
63 let stmt = make::expr_stmt(if_); 63 let stmt = make::expr_stmt(if_);
64 64
65 let placeholder = 65 let placeholder = stmt.syntax().descendants().find_map(ast::WildcardPat::cast).unwrap();
66 stmt.syntax().descendants().find_map(ast::PlaceholderPat::cast).unwrap();
67 let stmt = stmt.replace_descendant(placeholder.into(), original_pat); 66 let stmt = stmt.replace_descendant(placeholder.into(), original_pat);
68 67
69 edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt)); 68 edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt));
diff --git a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
index 3d51faa54..da0a860c5 100644
--- a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
@@ -25,7 +25,7 @@ pub(crate) fn replace_qualified_name_with_use(
25) -> Option<()> { 25) -> Option<()> {
26 let path: ast::Path = ctx.find_node_at_offset()?; 26 let path: ast::Path = ctx.find_node_at_offset()?;
27 // We don't want to mess with use statements 27 // We don't want to mess with use statements
28 if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() { 28 if path.syntax().ancestors().find_map(ast::Use::cast).is_some() {
29 return None; 29 return None;
30 } 30 }
31 31
@@ -85,7 +85,7 @@ fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path:
85 match child { 85 match child {
86 // Don't modify `use` items, as this can break the `use` item when injecting a new 86 // Don't modify `use` items, as this can break the `use` item when injecting a new
87 // import into the use tree. 87 // import into the use tree.
88 ast::UseItem(_it) => continue, 88 ast::Use(_it) => continue,
89 // Don't descend into submodules, they don't have the same `use` items in scope. 89 // Don't descend into submodules, they don't have the same `use` items in scope.
90 ast::Module(_it) => continue, 90 ast::Module(_it) => continue,
91 91
@@ -643,4 +643,46 @@ fn main() {
643 ", 643 ",
644 ); 644 );
645 } 645 }
646
647 #[test]
648 fn does_not_replace_pub_use() {
649 check_assist(
650 replace_qualified_name_with_use,
651 r"
652pub use std::fmt;
653
654impl std::io<|> for Foo {
655}
656 ",
657 r"
658use std::io;
659
660pub use std::fmt;
661
662impl io for Foo {
663}
664 ",
665 );
666 }
667
668 #[test]
669 fn does_not_replace_pub_crate_use() {
670 check_assist(
671 replace_qualified_name_with_use,
672 r"
673pub(crate) use std::fmt;
674
675impl std::io<|> for Foo {
676}
677 ",
678 r"
679use std::io;
680
681pub(crate) use std::fmt;
682
683impl io for Foo {
684}
685 ",
686 );
687 }
646} 688}
diff --git a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
index e5a4bb23c..d69f2c1b0 100644
--- a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
+++ b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
@@ -52,7 +52,7 @@ pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext)
52 target, 52 target,
53 |builder| { 53 |builder| {
54 let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant))); 54 let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant)));
55 let it = make::bind_pat(make::name("a")).into(); 55 let it = make::ident_pat(make::name("a")).into();
56 let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); 56 let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into();
57 57
58 let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); 58 let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a")));
@@ -60,7 +60,7 @@ pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext)
60 60
61 let unreachable_call = make::expr_unreachable(); 61 let unreachable_call = make::expr_unreachable();
62 let err_arm = 62 let err_arm =
63 make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call); 63 make::match_arm(iter::once(make::wildcard_pat().into()), unreachable_call);
64 64
65 let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); 65 let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]);
66 let match_expr = make::expr_match(caller.clone(), match_arm_list) 66 let match_expr = make::expr_match(caller.clone(), match_arm_list)
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 465b90415..507646cc8 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -140,6 +140,7 @@ mod handlers {
140 mod change_return_type_to_result; 140 mod change_return_type_to_result;
141 mod change_visibility; 141 mod change_visibility;
142 mod early_return; 142 mod early_return;
143 mod expand_glob_import;
143 mod extract_struct_from_enum_variant; 144 mod extract_struct_from_enum_variant;
144 mod extract_variable; 145 mod extract_variable;
145 mod fill_match_arms; 146 mod fill_match_arms;
@@ -181,6 +182,7 @@ mod handlers {
181 change_return_type_to_result::change_return_type_to_result, 182 change_return_type_to_result::change_return_type_to_result,
182 change_visibility::change_visibility, 183 change_visibility::change_visibility,
183 early_return::convert_to_guarded_return, 184 early_return::convert_to_guarded_return,
185 expand_glob_import::expand_glob_import,
184 extract_struct_from_enum_variant::extract_struct_from_enum_variant, 186 extract_struct_from_enum_variant::extract_struct_from_enum_variant,
185 extract_variable::extract_variable, 187 extract_variable::extract_variable,
186 fill_match_arms::fill_match_arms, 188 fill_match_arms::fill_match_arms,
diff --git a/crates/ra_assists/src/tests/generated.rs b/crates/ra_assists/src/tests/generated.rs
index eff7feded..97978e7a2 100644
--- a/crates/ra_assists/src/tests/generated.rs
+++ b/crates/ra_assists/src/tests/generated.rs
@@ -229,6 +229,33 @@ fn main() {
229} 229}
230 230
231#[test] 231#[test]
232fn doctest_expand_glob_import() {
233 check_doc_test(
234 "expand_glob_import",
235 r#####"
236mod foo {
237 pub struct Bar;
238 pub struct Baz;
239}
240
241use foo::*<|>;
242
243fn qux(bar: Bar, baz: Baz) {}
244"#####,
245 r#####"
246mod foo {
247 pub struct Bar;
248 pub struct Baz;
249}
250
251use foo::{Baz, Bar};
252
253fn qux(bar: Bar, baz: Baz) {}
254"#####,
255 )
256}
257
258#[test]
232fn doctest_extract_struct_from_enum_variant() { 259fn doctest_extract_struct_from_enum_variant() {
233 check_doc_test( 260 check_doc_test(
234 "extract_struct_from_enum_variant", 261 "extract_struct_from_enum_variant",
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs
index 02de902d6..54d5678d1 100644
--- a/crates/ra_assists/src/utils.rs
+++ b/crates/ra_assists/src/utils.rs
@@ -56,33 +56,34 @@ pub(crate) fn render_snippet(_cap: SnippetCap, node: &SyntaxNode, cursor: Cursor
56 56
57pub fn get_missing_assoc_items( 57pub fn get_missing_assoc_items(
58 sema: &Semantics<RootDatabase>, 58 sema: &Semantics<RootDatabase>,
59 impl_def: &ast::ImplDef, 59 impl_def: &ast::Impl,
60) -> Vec<hir::AssocItem> { 60) -> Vec<hir::AssocItem> {
61 // Names must be unique between constants and functions. However, type aliases 61 // Names must be unique between constants and functions. However, type aliases
62 // may share the same name as a function or constant. 62 // may share the same name as a function or constant.
63 let mut impl_fns_consts = FxHashSet::default(); 63 let mut impl_fns_consts = FxHashSet::default();
64 let mut impl_type = FxHashSet::default(); 64 let mut impl_type = FxHashSet::default();
65 65
66 if let Some(item_list) = impl_def.item_list() { 66 if let Some(item_list) = impl_def.assoc_item_list() {
67 for item in item_list.assoc_items() { 67 for item in item_list.assoc_items() {
68 match item { 68 match item {
69 ast::AssocItem::FnDef(f) => { 69 ast::AssocItem::Fn(f) => {
70 if let Some(n) = f.name() { 70 if let Some(n) = f.name() {
71 impl_fns_consts.insert(n.syntax().to_string()); 71 impl_fns_consts.insert(n.syntax().to_string());
72 } 72 }
73 } 73 }
74 74
75 ast::AssocItem::TypeAliasDef(t) => { 75 ast::AssocItem::TypeAlias(t) => {
76 if let Some(n) = t.name() { 76 if let Some(n) = t.name() {
77 impl_type.insert(n.syntax().to_string()); 77 impl_type.insert(n.syntax().to_string());
78 } 78 }
79 } 79 }
80 80
81 ast::AssocItem::ConstDef(c) => { 81 ast::AssocItem::Const(c) => {
82 if let Some(n) = c.name() { 82 if let Some(n) = c.name() {
83 impl_fns_consts.insert(n.syntax().to_string()); 83 impl_fns_consts.insert(n.syntax().to_string());
84 } 84 }
85 } 85 }
86 ast::AssocItem::MacroCall(_) => (),
86 } 87 }
87 } 88 }
88 } 89 }
@@ -108,13 +109,10 @@ pub fn get_missing_assoc_items(
108 109
109pub(crate) fn resolve_target_trait( 110pub(crate) fn resolve_target_trait(
110 sema: &Semantics<RootDatabase>, 111 sema: &Semantics<RootDatabase>,
111 impl_def: &ast::ImplDef, 112 impl_def: &ast::Impl,
112) -> Option<hir::Trait> { 113) -> Option<hir::Trait> {
113 let ast_path = impl_def 114 let ast_path =
114 .target_trait() 115 impl_def.trait_().map(|it| it.syntax().clone()).and_then(ast::PathType::cast)?.path()?;
115 .map(|it| it.syntax().clone())
116 .and_then(ast::PathType::cast)?
117 .path()?;
118 116
119 match sema.resolve_path(&ast_path) { 117 match sema.resolve_path(&ast_path) {
120 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def), 118 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def),
@@ -183,10 +181,10 @@ impl TryEnum {
183 match self { 181 match self {
184 TryEnum::Result => make::tuple_struct_pat( 182 TryEnum::Result => make::tuple_struct_pat(
185 make::path_unqualified(make::path_segment(make::name_ref("Err"))), 183 make::path_unqualified(make::path_segment(make::name_ref("Err"))),
186 iter::once(make::placeholder_pat().into()), 184 iter::once(make::wildcard_pat().into()),
187 ) 185 )
188 .into(), 186 .into(),
189 TryEnum::Option => make::bind_pat(make::name("None")).into(), 187 TryEnum::Option => make::ident_pat(make::name("None")).into(),
190 } 188 }
191 } 189 }
192 190
diff --git a/crates/ra_assists/src/utils/insert_use.rs b/crates/ra_assists/src/utils/insert_use.rs
index 8c4f33e59..32780fceb 100644
--- a/crates/ra_assists/src/utils/insert_use.rs
+++ b/crates/ra_assists/src/utils/insert_use.rs
@@ -4,7 +4,7 @@
4 4
5use hir::{self, ModPath}; 5use hir::{self, ModPath};
6use ra_syntax::{ 6use ra_syntax::{
7 ast::{self, NameOwner}, 7 ast::{self, NameOwner, VisibilityOwner},
8 AstNode, Direction, SmolStr, 8 AstNode, Direction, SmolStr,
9 SyntaxKind::{PATH, PATH_SEGMENT}, 9 SyntaxKind::{PATH, PATH_SEGMENT},
10 SyntaxNode, T, 10 SyntaxNode, T,
@@ -215,7 +215,7 @@ fn walk_use_tree_for_best_action(
215 let prev_len = current_path_segments.len(); 215 let prev_len = current_path_segments.len();
216 216
217 let tree_list = current_use_tree.use_tree_list(); 217 let tree_list = current_use_tree.use_tree_list();
218 let alias = current_use_tree.alias(); 218 let alias = current_use_tree.rename();
219 219
220 let path = match current_use_tree.path() { 220 let path = match current_use_tree.path() {
221 Some(path) => path, 221 Some(path) => path,
@@ -225,7 +225,7 @@ fn walk_use_tree_for_best_action(
225 current_use_tree 225 current_use_tree
226 .syntax() 226 .syntax()
227 .ancestors() 227 .ancestors()
228 .find_map(ast::UseItem::cast) 228 .find_map(ast::Use::cast)
229 .map(|it| it.syntax().clone()), 229 .map(|it| it.syntax().clone()),
230 true, 230 true,
231 ); 231 );
@@ -254,7 +254,7 @@ fn walk_use_tree_for_best_action(
254 current_use_tree 254 current_use_tree
255 .syntax() 255 .syntax()
256 .ancestors() 256 .ancestors()
257 .find_map(ast::UseItem::cast) 257 .find_map(ast::Use::cast)
258 .map(|it| it.syntax().clone()), 258 .map(|it| it.syntax().clone()),
259 true, 259 true,
260 ), 260 ),
@@ -304,7 +304,7 @@ fn walk_use_tree_for_best_action(
304 current_use_tree 304 current_use_tree
305 .syntax() 305 .syntax()
306 .ancestors() 306 .ancestors()
307 .find_map(ast::UseItem::cast) 307 .find_map(ast::Use::cast)
308 .map(|it| it.syntax().clone()), 308 .map(|it| it.syntax().clone()),
309 true, 309 true,
310 ); 310 );
@@ -377,7 +377,8 @@ fn best_action_for_target(
377 let mut storage = Vec::with_capacity(16); // this should be the only allocation 377 let mut storage = Vec::with_capacity(16); // this should be the only allocation
378 let best_action = container 378 let best_action = container
379 .children() 379 .children()
380 .filter_map(ast::UseItem::cast) 380 .filter_map(ast::Use::cast)
381 .filter(|u| u.visibility().is_none())
381 .filter_map(|it| it.use_tree()) 382 .filter_map(|it| it.use_tree())
382 .map(|u| walk_use_tree_for_best_action(&mut storage, None, u, target)) 383 .map(|u| walk_use_tree_for_best_action(&mut storage, None, u, target))
383 .fold(None, |best, a| match best { 384 .fold(None, |best, a| match best {