aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists/src')
-rw-r--r--crates/ide_assists/src/handlers/add_turbo_fish.rs2
-rw-r--r--crates/ide_assists/src/handlers/change_visibility.rs2
-rw-r--r--crates/ide_assists/src/handlers/expand_glob_import.rs2
-rw-r--r--crates/ide_assists/src/handlers/extract_function.rs20
-rw-r--r--crates/ide_assists/src/handlers/flip_trait_bound.rs2
-rw-r--r--crates/ide_assists/src/handlers/generate_is_empty_from_len.rs35
-rw-r--r--crates/ide_assists/src/handlers/invert_if.rs2
-rw-r--r--crates/ide_assists/src/handlers/move_bounds.rs62
-rw-r--r--crates/ide_assists/src/handlers/split_import.rs2
-rw-r--r--crates/ide_assists/src/handlers/unwrap_block.rs2
10 files changed, 60 insertions, 71 deletions
diff --git a/crates/ide_assists/src/handlers/add_turbo_fish.rs b/crates/ide_assists/src/handlers/add_turbo_fish.rs
index ee879c151..436767895 100644
--- a/crates/ide_assists/src/handlers/add_turbo_fish.rs
+++ b/crates/ide_assists/src/handlers/add_turbo_fish.rs
@@ -38,7 +38,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<(
38 cov_mark::hit!(add_turbo_fish_one_fish_is_enough); 38 cov_mark::hit!(add_turbo_fish_one_fish_is_enough);
39 return None; 39 return None;
40 } 40 }
41 let name_ref = ast::NameRef::cast(ident.parent())?; 41 let name_ref = ast::NameRef::cast(ident.parent()?)?;
42 let def = match NameRefClass::classify(&ctx.sema, &name_ref)? { 42 let def = match NameRefClass::classify(&ctx.sema, &name_ref)? {
43 NameRefClass::Definition(def) => def, 43 NameRefClass::Definition(def) => def,
44 NameRefClass::ExternCrate(_) | NameRefClass::FieldShorthand { .. } => return None, 44 NameRefClass::ExternCrate(_) | NameRefClass::FieldShorthand { .. } => return None,
diff --git a/crates/ide_assists/src/handlers/change_visibility.rs b/crates/ide_assists/src/handlers/change_visibility.rs
index ec99a5505..d7e39b2ae 100644
--- a/crates/ide_assists/src/handlers/change_visibility.rs
+++ b/crates/ide_assists/src/handlers/change_visibility.rs
@@ -41,7 +41,7 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
41 }); 41 });
42 42
43 let (offset, target) = if let Some(keyword) = item_keyword { 43 let (offset, target) = if let Some(keyword) = item_keyword {
44 let parent = keyword.parent(); 44 let parent = keyword.parent()?;
45 let def_kws = vec![CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT]; 45 let def_kws = vec![CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT];
46 // Parent is not a definition, can't add visibility 46 // Parent is not a definition, can't add visibility
47 if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) { 47 if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) {
diff --git a/crates/ide_assists/src/handlers/expand_glob_import.rs b/crates/ide_assists/src/handlers/expand_glob_import.rs
index 5fe617ba4..5b540df5c 100644
--- a/crates/ide_assists/src/handlers/expand_glob_import.rs
+++ b/crates/ide_assists/src/handlers/expand_glob_import.rs
@@ -48,7 +48,7 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti
48 _ => return None, 48 _ => return None,
49 }; 49 };
50 50
51 let current_scope = ctx.sema.scope(&star.parent()); 51 let current_scope = ctx.sema.scope(&star.parent()?);
52 let current_module = current_scope.module()?; 52 let current_module = current_scope.module()?;
53 53
54 let refs_in_target = find_refs_in_mod(ctx, target_module, Some(current_module))?; 54 let refs_in_target = find_refs_in_mod(ctx, target_module, Some(current_module))?;
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs
index dd4501709..5fdc8bf38 100644
--- a/crates/ide_assists/src/handlers/extract_function.rs
+++ b/crates/ide_assists/src/handlers/extract_function.rs
@@ -16,7 +16,6 @@ use syntax::{
16 edit::{AstNodeEdit, IndentLevel}, 16 edit::{AstNodeEdit, IndentLevel},
17 AstNode, 17 AstNode,
18 }, 18 },
19 SyntaxElement,
20 SyntaxKind::{self, BLOCK_EXPR, BREAK_EXPR, COMMENT, PATH_EXPR, RETURN_EXPR}, 19 SyntaxKind::{self, BLOCK_EXPR, BREAK_EXPR, COMMENT, PATH_EXPR, RETURN_EXPR},
21 SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, WalkEvent, T, 20 SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, WalkEvent, T,
22}; 21};
@@ -62,7 +61,10 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext) -> Option
62 return None; 61 return None;
63 } 62 }
64 63
65 let node = element_to_node(node); 64 let node = match node {
65 syntax::NodeOrToken::Node(n) => n,
66 syntax::NodeOrToken::Token(t) => t.parent()?,
67 };
66 68
67 let body = extraction_target(&node, ctx.frange.range)?; 69 let body = extraction_target(&node, ctx.frange.range)?;
68 70
@@ -560,14 +562,6 @@ impl HasTokenAtOffset for FunctionBody {
560 } 562 }
561} 563}
562 564
563/// node or token's parent
564fn element_to_node(node: SyntaxElement) -> SyntaxNode {
565 match node {
566 syntax::NodeOrToken::Node(n) => n,
567 syntax::NodeOrToken::Token(t) => t.parent(),
568 }
569}
570
571/// Try to guess what user wants to extract 565/// Try to guess what user wants to extract
572/// 566///
573/// We have basically have two cases: 567/// We have basically have two cases:
@@ -1246,7 +1240,7 @@ fn make_body(
1246 }) 1240 })
1247 } 1241 }
1248 FlowHandler::If { .. } => { 1242 FlowHandler::If { .. } => {
1249 let lit_false = ast::Literal::cast(make::tokens::literal("false").parent()).unwrap(); 1243 let lit_false = make::expr_literal("false");
1250 with_tail_expr(block, lit_false.into()) 1244 with_tail_expr(block, lit_false.into())
1251 } 1245 }
1252 FlowHandler::IfOption { .. } => { 1246 FlowHandler::IfOption { .. } => {
@@ -1420,9 +1414,7 @@ fn update_external_control_flow(handler: &FlowHandler, syntax: &SyntaxNode) -> S
1420fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option<ast::Expr>) -> Option<ast::Expr> { 1414fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option<ast::Expr>) -> Option<ast::Expr> {
1421 let value = match handler { 1415 let value = match handler {
1422 FlowHandler::None | FlowHandler::Try { .. } => return None, 1416 FlowHandler::None | FlowHandler::Try { .. } => return None,
1423 FlowHandler::If { .. } => { 1417 FlowHandler::If { .. } => make::expr_literal("true").into(),
1424 ast::Literal::cast(make::tokens::literal("true").parent()).unwrap().into()
1425 }
1426 FlowHandler::IfOption { .. } => { 1418 FlowHandler::IfOption { .. } => {
1427 let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new())); 1419 let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
1428 let args = make::arg_list(iter::once(expr)); 1420 let args = make::arg_list(iter::once(expr));
diff --git a/crates/ide_assists/src/handlers/flip_trait_bound.rs b/crates/ide_assists/src/handlers/flip_trait_bound.rs
index d419d263e..a868aa43d 100644
--- a/crates/ide_assists/src/handlers/flip_trait_bound.rs
+++ b/crates/ide_assists/src/handlers/flip_trait_bound.rs
@@ -23,7 +23,7 @@ pub(crate) fn flip_trait_bound(acc: &mut Assists, ctx: &AssistContext) -> Option
23 let plus = ctx.find_token_syntax_at_offset(T![+])?; 23 let plus = ctx.find_token_syntax_at_offset(T![+])?;
24 24
25 // Make sure we're in a `TypeBoundList` 25 // Make sure we're in a `TypeBoundList`
26 if ast::TypeBoundList::cast(plus.parent()).is_none() { 26 if ast::TypeBoundList::cast(plus.parent()?).is_none() {
27 return None; 27 return None;
28 } 28 }
29 29
diff --git a/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs b/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs
index aa7072f25..b8834d283 100644
--- a/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs
+++ b/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs
@@ -1,7 +1,7 @@
1use hir::{known, HasSource, Name}; 1use hir::{known, HasSource, Name};
2use syntax::{ 2use syntax::{
3 ast::{self, NameOwner}, 3 ast::{self, NameOwner},
4 AstNode, TextRange, 4 AstNode,
5}; 5};
6 6
7use crate::{ 7use crate::{
@@ -51,12 +51,19 @@ pub(crate) fn generate_is_empty_from_len(acc: &mut Assists, ctx: &AssistContext)
51 } 51 }
52 52
53 let impl_ = fn_node.syntax().ancestors().find_map(ast::Impl::cast)?; 53 let impl_ = fn_node.syntax().ancestors().find_map(ast::Impl::cast)?;
54 let len_fn = get_impl_method(ctx, &impl_, &known::len)?;
55 if !len_fn.ret_type(ctx.sema.db).is_usize() {
56 cov_mark::hit!(len_fn_different_return_type);
57 return None;
58 }
59
54 if get_impl_method(ctx, &impl_, &known::is_empty).is_some() { 60 if get_impl_method(ctx, &impl_, &known::is_empty).is_some() {
55 cov_mark::hit!(is_empty_already_implemented); 61 cov_mark::hit!(is_empty_already_implemented);
56 return None; 62 return None;
57 } 63 }
58 64
59 let range = get_text_range_of_len_function(ctx, &impl_)?; 65 let node = len_fn.source(ctx.sema.db)?;
66 let range = node.syntax().value.text_range();
60 67
61 acc.add( 68 acc.add(
62 AssistId("generate_is_empty_from_len", AssistKind::Generate), 69 AssistId("generate_is_empty_from_len", AssistKind::Generate),
@@ -89,13 +96,6 @@ fn get_impl_method(
89 ty.iterate_method_candidates(db, krate, &traits_in_scope, Some(fn_name), |_, func| Some(func)) 96 ty.iterate_method_candidates(db, krate, &traits_in_scope, Some(fn_name), |_, func| Some(func))
90} 97}
91 98
92fn get_text_range_of_len_function(ctx: &AssistContext, impl_: &ast::Impl) -> Option<TextRange> {
93 let db = ctx.sema.db;
94 let func = get_impl_method(ctx, impl_, &known::len)?;
95 let node = func.source(db)?;
96 Some(node.syntax().value.text_range())
97}
98
99#[cfg(test)] 99#[cfg(test)]
100mod tests { 100mod tests {
101 use crate::tests::{check_assist, check_assist_not_applicable}; 101 use crate::tests::{check_assist, check_assist_not_applicable};
@@ -158,6 +158,23 @@ impl MyStruct {
158 } 158 }
159 159
160 #[test] 160 #[test]
161 fn len_fn_different_return_type() {
162 cov_mark::check!(len_fn_different_return_type);
163 check_assist_not_applicable(
164 generate_is_empty_from_len,
165 r#"
166struct MyStruct { data: Vec<String> }
167
168impl MyStruct {
169 p$0ub fn len(&self) -> u32 {
170 self.data.len()
171 }
172}
173"#,
174 );
175 }
176
177 #[test]
161 fn generate_is_empty() { 178 fn generate_is_empty() {
162 check_assist( 179 check_assist(
163 generate_is_empty_from_len, 180 generate_is_empty_from_len,
diff --git a/crates/ide_assists/src/handlers/invert_if.rs b/crates/ide_assists/src/handlers/invert_if.rs
index b131dc205..53612ec3f 100644
--- a/crates/ide_assists/src/handlers/invert_if.rs
+++ b/crates/ide_assists/src/handlers/invert_if.rs
@@ -30,7 +30,7 @@ use crate::{
30 30
31pub(crate) fn invert_if(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 31pub(crate) fn invert_if(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
32 let if_keyword = ctx.find_token_syntax_at_offset(T![if])?; 32 let if_keyword = ctx.find_token_syntax_at_offset(T![if])?;
33 let expr = ast::IfExpr::cast(if_keyword.parent())?; 33 let expr = ast::IfExpr::cast(if_keyword.parent()?)?;
34 let if_range = if_keyword.text_range(); 34 let if_range = if_keyword.text_range();
35 let cursor_in_range = if_range.contains_range(ctx.frange.range); 35 let cursor_in_range = if_range.contains_range(ctx.frange.range);
36 if !cursor_in_range { 36 if !cursor_in_range {
diff --git a/crates/ide_assists/src/handlers/move_bounds.rs b/crates/ide_assists/src/handlers/move_bounds.rs
index cf260c6f8..48efa67ed 100644
--- a/crates/ide_assists/src/handlers/move_bounds.rs
+++ b/crates/ide_assists/src/handlers/move_bounds.rs
@@ -1,8 +1,6 @@
1use syntax::{ 1use syntax::{
2 ast::{self, edit::AstNodeEdit, make, AstNode, NameOwner, TypeBoundsOwner}, 2 ast::{self, edit_in_place::GenericParamsOwnerEdit, make, AstNode, NameOwner, TypeBoundsOwner},
3 match_ast, 3 match_ast,
4 SyntaxKind::*,
5 T,
6}; 4};
7 5
8use crate::{AssistContext, AssistId, AssistKind, Assists}; 6use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -23,7 +21,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
23// } 21// }
24// ``` 22// ```
25pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 23pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
26 let type_param_list = ctx.find_node_at_offset::<ast::GenericParamList>()?; 24 let type_param_list = ctx.find_node_at_offset::<ast::GenericParamList>()?.clone_for_update();
27 25
28 let mut type_params = type_param_list.type_params(); 26 let mut type_params = type_param_list.type_params();
29 if type_params.all(|p| p.type_bound_list().is_none()) { 27 if type_params.all(|p| p.type_bound_list().is_none()) {
@@ -31,23 +29,7 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext
31 } 29 }
32 30
33 let parent = type_param_list.syntax().parent()?; 31 let parent = type_param_list.syntax().parent()?;
34 if parent.children_with_tokens().any(|it| it.kind() == WHERE_CLAUSE) { 32 let original_parent_range = parent.text_range();
35 return None;
36 }
37
38 let anchor = match_ast! {
39 match parent {
40 ast::Fn(it) => it.body()?.syntax().clone().into(),
41 ast::Trait(it) => it.assoc_item_list()?.syntax().clone().into(),
42 ast::Impl(it) => it.assoc_item_list()?.syntax().clone().into(),
43 ast::Enum(it) => it.variant_list()?.syntax().clone().into(),
44 ast::Struct(it) => {
45 it.syntax().children_with_tokens()
46 .find(|it| it.kind() == RECORD_FIELD_LIST || it.kind() == T![;])?
47 },
48 _ => return None
49 }
50 };
51 33
52 let target = type_param_list.syntax().text_range(); 34 let target = type_param_list.syntax().text_range();
53 acc.add( 35 acc.add(
@@ -55,29 +37,27 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext
55 "Move to where clause", 37 "Move to where clause",
56 target, 38 target,
57 |edit| { 39 |edit| {
58 let new_params = type_param_list 40 let where_clause: ast::WhereClause = match_ast! {
59 .type_params() 41 match parent {
60 .filter(|it| it.type_bound_list().is_some()) 42 ast::Fn(it) => it.get_or_create_where_clause(),
61 .map(|type_param| { 43 // ast::Trait(it) => it.get_or_create_where_clause(),
62 let without_bounds = type_param.remove_bounds(); 44 ast::Impl(it) => it.get_or_create_where_clause(),
63 (type_param, without_bounds) 45 // ast::Enum(it) => it.get_or_create_where_clause(),
64 }); 46 ast::Struct(it) => it.get_or_create_where_clause(),
65 47 _ => return,
66 let new_type_param_list = type_param_list.replace_descendants(new_params); 48 }
67 edit.replace_ast(type_param_list.clone(), new_type_param_list);
68
69 let where_clause = {
70 let predicates = type_param_list.type_params().filter_map(build_predicate);
71 make::where_clause(predicates)
72 }; 49 };
73 50
74 let to_insert = match anchor.prev_sibling_or_token() { 51 for type_param in type_param_list.type_params() {
75 Some(ref elem) if elem.kind() == WHITESPACE => { 52 if let Some(tbl) = type_param.type_bound_list() {
76 format!("{} ", where_clause.syntax()) 53 if let Some(predicate) = build_predicate(type_param.clone()) {
54 where_clause.add_predicate(predicate.clone_for_update())
55 }
56 tbl.remove()
77 } 57 }
78 _ => format!(" {}", where_clause.syntax()), 58 }
79 }; 59
80 edit.insert(anchor.text_range().start(), to_insert); 60 edit.replace(original_parent_range, parent.to_string())
81 }, 61 },
82 ) 62 )
83} 63}
diff --git a/crates/ide_assists/src/handlers/split_import.rs b/crates/ide_assists/src/handlers/split_import.rs
index 9319a4267..446f30544 100644
--- a/crates/ide_assists/src/handlers/split_import.rs
+++ b/crates/ide_assists/src/handlers/split_import.rs
@@ -17,7 +17,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
17// ``` 17// ```
18pub(crate) fn split_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 18pub(crate) fn split_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
19 let colon_colon = ctx.find_token_syntax_at_offset(T![::])?; 19 let colon_colon = ctx.find_token_syntax_at_offset(T![::])?;
20 let path = ast::Path::cast(colon_colon.parent())?.qualifier()?; 20 let path = ast::Path::cast(colon_colon.parent()?)?.qualifier()?;
21 let top_path = successors(Some(path.clone()), |it| it.parent_path()).last()?; 21 let top_path = successors(Some(path.clone()), |it| it.parent_path()).last()?;
22 22
23 let use_tree = top_path.syntax().ancestors().find_map(ast::UseTree::cast)?; 23 let use_tree = top_path.syntax().ancestors().find_map(ast::UseTree::cast)?;
diff --git a/crates/ide_assists/src/handlers/unwrap_block.rs b/crates/ide_assists/src/handlers/unwrap_block.rs
index ed6f6177d..440639322 100644
--- a/crates/ide_assists/src/handlers/unwrap_block.rs
+++ b/crates/ide_assists/src/handlers/unwrap_block.rs
@@ -30,7 +30,7 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
30 let assist_label = "Unwrap block"; 30 let assist_label = "Unwrap block";
31 31
32 let l_curly_token = ctx.find_token_syntax_at_offset(T!['{'])?; 32 let l_curly_token = ctx.find_token_syntax_at_offset(T!['{'])?;
33 let mut block = ast::BlockExpr::cast(l_curly_token.parent())?; 33 let mut block = ast::BlockExpr::cast(l_curly_token.parent()?)?;
34 let target = block.syntax().text_range(); 34 let target = block.syntax().text_range();
35 let mut parent = block.syntax().parent()?; 35 let mut parent = block.syntax().parent()?;
36 if ast::MatchArm::can_cast(parent.kind()) { 36 if ast::MatchArm::can_cast(parent.kind()) {