diff options
Diffstat (limited to 'crates/ra_assists/src')
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 | ||
33 | pub struct SubstituteTypeParams<'a> { | 33 | pub 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 | // ``` |
31 | pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 31 | pub(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 @@ | |||
1 | use hir::HirDisplay; | 1 | use hir::HirDisplay; |
2 | use ra_syntax::{ | 2 | use 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 | // ``` |
24 | pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 24 | pub(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 | ||
194 | fn add_body(fn_def: ast::FnDef) -> ast::FnDef { | 193 | fn 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; | |||
20 | pub(crate) fn change_return_type_to_result(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 20 | pub(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 @@ | |||
1 | use ra_syntax::{ | 1 | use 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 | }; |
9 | use test_utils::mark; | 7 | use 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 @@ | |||
1 | use hir::{AssocItem, MacroDef, ModuleDef, Name, PathResolution, ScopeDef, SemanticsScope}; | ||
2 | use ra_ide_db::{ | ||
3 | defs::{classify_name_ref, Definition, NameRefClass}, | ||
4 | RootDatabase, | ||
5 | }; | ||
6 | use ra_syntax::{algo, ast, match_ast, AstNode, SyntaxNode, SyntaxToken, T}; | ||
7 | |||
8 | use crate::{ | ||
9 | assist_context::{AssistBuilder, AssistContext, Assists}, | ||
10 | AssistId, AssistKind, | ||
11 | }; | ||
12 | |||
13 | use 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 | // ``` | ||
40 | pub(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 | |||
63 | fn 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)] | ||
68 | enum Def { | ||
69 | ModuleDef(ModuleDef), | ||
70 | MacroDef(MacroDef), | ||
71 | } | ||
72 | |||
73 | impl 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 | |||
82 | fn 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 | |||
110 | fn 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 | |||
144 | fn 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)] | ||
184 | mod 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" | ||
194 | mod foo { | ||
195 | pub struct Bar; | ||
196 | pub struct Baz; | ||
197 | pub struct Qux; | ||
198 | |||
199 | pub fn f() {} | ||
200 | } | ||
201 | |||
202 | use foo::*<|>; | ||
203 | |||
204 | fn qux(bar: Bar, baz: Baz) { | ||
205 | f(); | ||
206 | } | ||
207 | ", | ||
208 | r" | ||
209 | mod foo { | ||
210 | pub struct Bar; | ||
211 | pub struct Baz; | ||
212 | pub struct Qux; | ||
213 | |||
214 | pub fn f() {} | ||
215 | } | ||
216 | |||
217 | use foo::{Baz, Bar, f}; | ||
218 | |||
219 | fn 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" | ||
231 | mod foo { | ||
232 | pub struct Bar; | ||
233 | pub struct Baz; | ||
234 | pub struct Qux; | ||
235 | |||
236 | pub fn f() {} | ||
237 | } | ||
238 | |||
239 | use foo::{*<|>, f}; | ||
240 | |||
241 | fn qux(bar: Bar, baz: Baz) { | ||
242 | f(); | ||
243 | } | ||
244 | ", | ||
245 | r" | ||
246 | mod foo { | ||
247 | pub struct Bar; | ||
248 | pub struct Baz; | ||
249 | pub struct Qux; | ||
250 | |||
251 | pub fn f() {} | ||
252 | } | ||
253 | |||
254 | use foo::{Baz, Bar, f}; | ||
255 | |||
256 | fn 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" | ||
268 | mod 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 | |||
282 | use foo::{bar::{*<|>, f}, baz::*}; | ||
283 | |||
284 | fn qux(bar: Bar, baz: Baz) { | ||
285 | f(); | ||
286 | g(); | ||
287 | } | ||
288 | ", | ||
289 | r" | ||
290 | mod 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 | |||
304 | use foo::{bar::{Baz, Bar, f}, baz::*}; | ||
305 | |||
306 | fn 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] | ||
321 | macro_rules! bar { | ||
322 | () => () | ||
323 | } | ||
324 | |||
325 | pub fn baz() {} | ||
326 | |||
327 | //- /main.rs crate:main deps:foo | ||
328 | use foo::*<|>; | ||
329 | |||
330 | fn main() { | ||
331 | bar!(); | ||
332 | baz(); | ||
333 | } | ||
334 | ", | ||
335 | r" | ||
336 | use foo::{bar, baz}; | ||
337 | |||
338 | fn 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 | ||
352 | pub trait Tr { | ||
353 | fn method(&self) {} | ||
354 | } | ||
355 | impl Tr for () {} | ||
356 | |||
357 | //- /main.rs crate:main deps:foo | ||
358 | use foo::*<|>; | ||
359 | |||
360 | fn main() { | ||
361 | ().method(); | ||
362 | } | ||
363 | ", | ||
364 | r" | ||
365 | use foo::Tr; | ||
366 | |||
367 | fn 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 @@ | |||
1 | use ra_syntax::{ | 1 | use 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 | ||
84 | fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 84 | fn 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 | // ``` |
27 | pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 27 | pub(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. |
61 | fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextSize> { | 61 | fn 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 | // ``` |
24 | pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 24 | pub(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 | ||
70 | fn existing_from_impl( | 70 | fn 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 { | |||
104 | struct FunctionBuilder { | 104 | struct 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 @@ | |||
1 | use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; | 1 | use ra_syntax::ast::{self, AstNode, GenericParamsOwner, NameOwner}; |
2 | use stdx::{format_to, SepBy}; | 2 | use stdx::{format_to, SepBy}; |
3 | 3 | ||
4 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 4 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
@@ -23,7 +23,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
23 | // } | 23 | // } |
24 | // ``` | 24 | // ``` |
25 | pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 25 | pub(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 @@ | |||
1 | use hir::Adt; | 1 | use hir::Adt; |
2 | use ra_syntax::{ | 2 | use 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 | }; |
8 | use stdx::{format_to, SepBy}; | 6 | use stdx::{format_to, SepBy}; |
@@ -30,7 +28,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
30 | // | 28 | // |
31 | // ``` | 29 | // ``` |
32 | pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 30 | pub(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 |
93 | fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String { | 89 | fn 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) |
124 | fn find_struct_impl(ctx: &AssistContext, strukt: &ast::StructDef) -> Option<Option<ast::ImplDef>> { | 120 | fn 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 | ||
160 | fn has_new_fn(imp: &ast::ImplDef) -> bool { | 156 | fn 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::{ | |||
29 | pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 29 | pub(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 @@ | |||
1 | use ra_syntax::{ | 1 | use 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 | }; |
5 | use rustc_hash::FxHashSet; | 5 | use 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 |
51 | fn generate_fn_def_assist( | 51 | fn 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 |
94 | fn generate_impl_def_assist( | 94 | fn 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 |
109 | fn generate_unique_lifetime_param_name( | 109 | fn 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`. |
126 | fn add_lifetime_param<TypeParamsOwner: ast::TypeParamsOwner>( | 126 | fn 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 | ||
88 | fn contains_placeholder(a: &ast::MatchArm) -> bool { | 88 | fn 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 | // ``` |
25 | pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 25 | pub(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)] |
176 | mod test { | 176 | mod 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 @@ | |||
1 | use ra_syntax::{ | 1 | use ra_syntax::{ |
2 | ast::{self, AstNode}, | 2 | ast::{self, AstNode}, |
3 | TextSize, T, | 3 | TextRange, TextSize, T, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 6 | use 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#" | ||
172 | fn square(x: u32) -> u32 { | ||
173 | x * x | ||
174 | } | ||
175 | |||
176 | fn 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#" | ||
186 | fn square(x: u32) -> u32 { | ||
187 | x * x | ||
188 | } | ||
189 | |||
190 | fn main() { | ||
191 | let x = square(dbg<|>!(5 + 10)); | ||
192 | println!("{}", x); | ||
193 | }"#, | ||
194 | r#" | ||
195 | fn square(x: u32) -> u32 { | ||
196 | x * x | ||
197 | } | ||
198 | |||
199 | fn 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 | // |
25 | pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 25 | pub(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 | ||
29 | fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 29 | fn 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 | ||
57 | fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> { | 57 | fn 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> { | |||
65 | fn get_field_name(node: &SyntaxNode) -> String { | 65 | fn 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" | ||
652 | pub use std::fmt; | ||
653 | |||
654 | impl std::io<|> for Foo { | ||
655 | } | ||
656 | ", | ||
657 | r" | ||
658 | use std::io; | ||
659 | |||
660 | pub use std::fmt; | ||
661 | |||
662 | impl 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" | ||
673 | pub(crate) use std::fmt; | ||
674 | |||
675 | impl std::io<|> for Foo { | ||
676 | } | ||
677 | ", | ||
678 | r" | ||
679 | use std::io; | ||
680 | |||
681 | pub(crate) use std::fmt; | ||
682 | |||
683 | impl 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] |
232 | fn doctest_expand_glob_import() { | ||
233 | check_doc_test( | ||
234 | "expand_glob_import", | ||
235 | r#####" | ||
236 | mod foo { | ||
237 | pub struct Bar; | ||
238 | pub struct Baz; | ||
239 | } | ||
240 | |||
241 | use foo::*<|>; | ||
242 | |||
243 | fn qux(bar: Bar, baz: Baz) {} | ||
244 | "#####, | ||
245 | r#####" | ||
246 | mod foo { | ||
247 | pub struct Bar; | ||
248 | pub struct Baz; | ||
249 | } | ||
250 | |||
251 | use foo::{Baz, Bar}; | ||
252 | |||
253 | fn qux(bar: Bar, baz: Baz) {} | ||
254 | "#####, | ||
255 | ) | ||
256 | } | ||
257 | |||
258 | #[test] | ||
232 | fn doctest_extract_struct_from_enum_variant() { | 259 | fn 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 | ||
57 | pub fn get_missing_assoc_items( | 57 | pub 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 | ||
109 | pub(crate) fn resolve_target_trait( | 110 | pub(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 | ||
5 | use hir::{self, ModPath}; | 5 | use hir::{self, ModPath}; |
6 | use ra_syntax::{ | 6 | use 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 { |