diff options
Diffstat (limited to 'crates/assists')
-rw-r--r-- | crates/assists/src/ast_transform.rs | 32 | ||||
-rw-r--r-- | crates/assists/src/handlers/add_missing_impl_members.rs | 63 | ||||
-rw-r--r-- | crates/assists/src/handlers/auto_import.rs | 2 | ||||
-rw-r--r-- | crates/assists/src/handlers/expand_glob_import.rs | 20 | ||||
-rw-r--r-- | crates/assists/src/handlers/extract_struct_from_enum_variant.rs | 7 | ||||
-rw-r--r-- | crates/assists/src/handlers/replace_qualified_name_with_use.rs | 50 | ||||
-rw-r--r-- | crates/assists/src/lib.rs | 37 | ||||
-rw-r--r-- | crates/assists/src/tests/generated.rs | 3 | ||||
-rw-r--r-- | crates/assists/src/utils/insert_use.rs | 5 |
9 files changed, 120 insertions, 99 deletions
diff --git a/crates/assists/src/ast_transform.rs b/crates/assists/src/ast_transform.rs index 4c41c16d8..5216862ba 100644 --- a/crates/assists/src/ast_transform.rs +++ b/crates/assists/src/ast_transform.rs | |||
@@ -7,6 +7,17 @@ use syntax::{ | |||
7 | ast::{self, AstNode}, | 7 | ast::{self, AstNode}, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N { | ||
11 | SyntaxRewriter::from_fn(|element| match element { | ||
12 | syntax::SyntaxElement::Node(n) => { | ||
13 | let replacement = transformer.get_substitution(&n)?; | ||
14 | Some(replacement.into()) | ||
15 | } | ||
16 | _ => None, | ||
17 | }) | ||
18 | .rewrite_ast(&node) | ||
19 | } | ||
20 | |||
10 | pub trait AstTransform<'a> { | 21 | pub trait AstTransform<'a> { |
11 | fn get_substitution(&self, node: &syntax::SyntaxNode) -> Option<syntax::SyntaxNode>; | 22 | fn get_substitution(&self, node: &syntax::SyntaxNode) -> Option<syntax::SyntaxNode>; |
12 | 23 | ||
@@ -107,10 +118,7 @@ impl<'a> SubstituteTypeParams<'a> { | |||
107 | ast::Type::PathType(path_type) => path_type.path()?, | 118 | ast::Type::PathType(path_type) => path_type.path()?, |
108 | _ => return None, | 119 | _ => return None, |
109 | }; | 120 | }; |
110 | // FIXME: use `hir::Path::from_src` instead. | 121 | let resolution = self.source_scope.speculative_resolve(&path)?; |
111 | #[allow(deprecated)] | ||
112 | let path = hir::Path::from_ast(path)?; | ||
113 | let resolution = self.source_scope.resolve_hir_path(&path)?; | ||
114 | match resolution { | 122 | match resolution { |
115 | hir::PathResolution::TypeParam(tp) => Some(self.substs.get(&tp)?.syntax().clone()), | 123 | hir::PathResolution::TypeParam(tp) => Some(self.substs.get(&tp)?.syntax().clone()), |
116 | _ => None, | 124 | _ => None, |
@@ -146,10 +154,7 @@ impl<'a> QualifyPaths<'a> { | |||
146 | // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway | 154 | // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway |
147 | return None; | 155 | return None; |
148 | } | 156 | } |
149 | // FIXME: use `hir::Path::from_src` instead. | 157 | let resolution = self.source_scope.speculative_resolve(&p)?; |
150 | #[allow(deprecated)] | ||
151 | let hir_path = hir::Path::from_ast(p.clone()); | ||
152 | let resolution = self.source_scope.resolve_hir_path(&hir_path?)?; | ||
153 | match resolution { | 158 | match resolution { |
154 | PathResolution::Def(def) => { | 159 | PathResolution::Def(def) => { |
155 | let found_path = from.find_use_path(self.source_scope.db.upcast(), def)?; | 160 | let found_path = from.find_use_path(self.source_scope.db.upcast(), def)?; |
@@ -175,17 +180,6 @@ impl<'a> QualifyPaths<'a> { | |||
175 | } | 180 | } |
176 | } | 181 | } |
177 | 182 | ||
178 | pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N { | ||
179 | SyntaxRewriter::from_fn(|element| match element { | ||
180 | syntax::SyntaxElement::Node(n) => { | ||
181 | let replacement = transformer.get_substitution(&n)?; | ||
182 | Some(replacement.into()) | ||
183 | } | ||
184 | _ => None, | ||
185 | }) | ||
186 | .rewrite_ast(&node) | ||
187 | } | ||
188 | |||
189 | impl<'a> AstTransform<'a> for QualifyPaths<'a> { | 183 | impl<'a> AstTransform<'a> for QualifyPaths<'a> { |
190 | fn get_substitution(&self, node: &syntax::SyntaxNode) -> Option<syntax::SyntaxNode> { | 184 | fn get_substitution(&self, node: &syntax::SyntaxNode) -> Option<syntax::SyntaxNode> { |
191 | self.get_substitution_inner(node).or_else(|| self.previous.get_substitution(node)) | 185 | self.get_substitution_inner(node).or_else(|| self.previous.get_substitution(node)) |
diff --git a/crates/assists/src/handlers/add_missing_impl_members.rs b/crates/assists/src/handlers/add_missing_impl_members.rs index 81b61ebf8..83a2ada9a 100644 --- a/crates/assists/src/handlers/add_missing_impl_members.rs +++ b/crates/assists/src/handlers/add_missing_impl_members.rs | |||
@@ -48,7 +48,6 @@ enum AddMissingImplMembersMode { | |||
48 | // fn foo(&self) -> u32 { | 48 | // fn foo(&self) -> u32 { |
49 | // ${0:todo!()} | 49 | // ${0:todo!()} |
50 | // } | 50 | // } |
51 | // | ||
52 | // } | 51 | // } |
53 | // ``` | 52 | // ``` |
54 | pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 53 | pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
@@ -89,8 +88,8 @@ pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext) - | |||
89 | // impl Trait for () { | 88 | // impl Trait for () { |
90 | // Type X = (); | 89 | // Type X = (); |
91 | // fn foo(&self) {} | 90 | // fn foo(&self) {} |
92 | // $0fn bar(&self) {} | ||
93 | // | 91 | // |
92 | // $0fn bar(&self) {} | ||
94 | // } | 93 | // } |
95 | // ``` | 94 | // ``` |
96 | pub(crate) fn add_missing_default_members(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 95 | pub(crate) fn add_missing_default_members(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
@@ -240,15 +239,18 @@ struct S; | |||
240 | 239 | ||
241 | impl Foo for S { | 240 | impl Foo for S { |
242 | fn bar(&self) {} | 241 | fn bar(&self) {} |
242 | |||
243 | $0type Output; | 243 | $0type Output; |
244 | |||
244 | const CONST: usize = 42; | 245 | const CONST: usize = 42; |
246 | |||
245 | fn foo(&self) { | 247 | fn foo(&self) { |
246 | todo!() | 248 | todo!() |
247 | } | 249 | } |
250 | |||
248 | fn baz(&self) { | 251 | fn baz(&self) { |
249 | todo!() | 252 | todo!() |
250 | } | 253 | } |
251 | |||
252 | }"#, | 254 | }"#, |
253 | ); | 255 | ); |
254 | } | 256 | } |
@@ -281,10 +283,10 @@ struct S; | |||
281 | 283 | ||
282 | impl Foo for S { | 284 | impl Foo for S { |
283 | fn bar(&self) {} | 285 | fn bar(&self) {} |
286 | |||
284 | fn foo(&self) { | 287 | fn foo(&self) { |
285 | ${0:todo!()} | 288 | ${0:todo!()} |
286 | } | 289 | } |
287 | |||
288 | }"#, | 290 | }"#, |
289 | ); | 291 | ); |
290 | } | 292 | } |
@@ -599,6 +601,7 @@ trait Foo { | |||
599 | struct S; | 601 | struct S; |
600 | impl Foo for S { | 602 | impl Foo for S { |
601 | $0type Output; | 603 | $0type Output; |
604 | |||
602 | fn foo(&self) { | 605 | fn foo(&self) { |
603 | todo!() | 606 | todo!() |
604 | } | 607 | } |
@@ -708,4 +711,56 @@ impl Tr for () { | |||
708 | }"#, | 711 | }"#, |
709 | ) | 712 | ) |
710 | } | 713 | } |
714 | |||
715 | #[test] | ||
716 | fn test_whitespace_fixup_preserves_bad_tokens() { | ||
717 | check_assist( | ||
718 | add_missing_impl_members, | ||
719 | r#" | ||
720 | trait Tr { | ||
721 | fn foo(); | ||
722 | } | ||
723 | |||
724 | impl Tr for ()<|> { | ||
725 | +++ | ||
726 | }"#, | ||
727 | r#" | ||
728 | trait Tr { | ||
729 | fn foo(); | ||
730 | } | ||
731 | |||
732 | impl Tr for () { | ||
733 | fn foo() { | ||
734 | ${0:todo!()} | ||
735 | } | ||
736 | +++ | ||
737 | }"#, | ||
738 | ) | ||
739 | } | ||
740 | |||
741 | #[test] | ||
742 | fn test_whitespace_fixup_preserves_comments() { | ||
743 | check_assist( | ||
744 | add_missing_impl_members, | ||
745 | r#" | ||
746 | trait Tr { | ||
747 | fn foo(); | ||
748 | } | ||
749 | |||
750 | impl Tr for ()<|> { | ||
751 | // very important | ||
752 | }"#, | ||
753 | r#" | ||
754 | trait Tr { | ||
755 | fn foo(); | ||
756 | } | ||
757 | |||
758 | impl Tr for () { | ||
759 | fn foo() { | ||
760 | ${0:todo!()} | ||
761 | } | ||
762 | // very important | ||
763 | }"#, | ||
764 | ) | ||
765 | } | ||
711 | } | 766 | } |
diff --git a/crates/assists/src/handlers/auto_import.rs b/crates/assists/src/handlers/auto_import.rs index cce789972..b9ec3f10b 100644 --- a/crates/assists/src/handlers/auto_import.rs +++ b/crates/assists/src/handlers/auto_import.rs | |||
@@ -53,7 +53,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
53 | |builder| { | 53 | |builder| { |
54 | insert_use_statement( | 54 | insert_use_statement( |
55 | &auto_import_assets.syntax_under_caret, | 55 | &auto_import_assets.syntax_under_caret, |
56 | &import, | 56 | &import.to_string(), |
57 | ctx, | 57 | ctx, |
58 | builder.text_edit_builder(), | 58 | builder.text_edit_builder(), |
59 | ); | 59 | ); |
diff --git a/crates/assists/src/handlers/expand_glob_import.rs b/crates/assists/src/handlers/expand_glob_import.rs index f690ec343..81d0af2f3 100644 --- a/crates/assists/src/handlers/expand_glob_import.rs +++ b/crates/assists/src/handlers/expand_glob_import.rs | |||
@@ -1,3 +1,4 @@ | |||
1 | use either::Either; | ||
1 | use hir::{AssocItem, MacroDef, ModuleDef, Name, PathResolution, ScopeDef, SemanticsScope}; | 2 | use hir::{AssocItem, MacroDef, ModuleDef, Name, PathResolution, ScopeDef, SemanticsScope}; |
2 | use ide_db::{ | 3 | use ide_db::{ |
3 | defs::{classify_name_ref, Definition, NameRefClass}, | 4 | defs::{classify_name_ref, Definition, NameRefClass}, |
@@ -10,8 +11,6 @@ use crate::{ | |||
10 | AssistId, AssistKind, | 11 | AssistId, AssistKind, |
11 | }; | 12 | }; |
12 | 13 | ||
13 | use either::Either; | ||
14 | |||
15 | // Assist: expand_glob_import | 14 | // Assist: expand_glob_import |
16 | // | 15 | // |
17 | // Expands glob imports. | 16 | // Expands glob imports. |
@@ -40,11 +39,15 @@ use either::Either; | |||
40 | pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 39 | pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
41 | let star = ctx.find_token_at_offset(T![*])?; | 40 | let star = ctx.find_token_at_offset(T![*])?; |
42 | let mod_path = find_mod_path(&star)?; | 41 | let mod_path = find_mod_path(&star)?; |
42 | let module = match ctx.sema.resolve_path(&mod_path)? { | ||
43 | PathResolution::Def(ModuleDef::Module(it)) => it, | ||
44 | _ => return None, | ||
45 | }; | ||
43 | 46 | ||
44 | let source_file = ctx.source_file(); | 47 | let source_file = ctx.source_file(); |
45 | let scope = ctx.sema.scope_at_offset(source_file.syntax(), ctx.offset()); | 48 | let scope = ctx.sema.scope_at_offset(source_file.syntax(), ctx.offset()); |
46 | 49 | ||
47 | let defs_in_mod = find_defs_in_mod(ctx, scope, &mod_path)?; | 50 | let defs_in_mod = find_defs_in_mod(ctx, scope, module)?; |
48 | let name_refs_in_source_file = | 51 | let name_refs_in_source_file = |
49 | source_file.syntax().descendants().filter_map(ast::NameRef::cast).collect(); | 52 | 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); | 53 | let used_names = find_used_names(ctx, defs_in_mod, name_refs_in_source_file); |
@@ -82,17 +85,8 @@ impl Def { | |||
82 | fn find_defs_in_mod( | 85 | fn find_defs_in_mod( |
83 | ctx: &AssistContext, | 86 | ctx: &AssistContext, |
84 | from: SemanticsScope<'_>, | 87 | from: SemanticsScope<'_>, |
85 | path: &ast::Path, | 88 | module: hir::Module, |
86 | ) -> Option<Vec<Def>> { | 89 | ) -> 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()); | 90 | let module_scope = module.scope(ctx.db(), from.module()); |
97 | 91 | ||
98 | let mut defs = vec![]; | 92 | let mut defs = vec![]; |
diff --git a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs index 4bcdae7ba..d62e06b4a 100644 --- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs | |||
@@ -106,7 +106,12 @@ fn insert_import( | |||
106 | if let Some(mut mod_path) = mod_path { | 106 | if let Some(mut mod_path) = mod_path { |
107 | mod_path.segments.pop(); | 107 | mod_path.segments.pop(); |
108 | mod_path.segments.push(variant_hir_name.clone()); | 108 | mod_path.segments.push(variant_hir_name.clone()); |
109 | insert_use_statement(path.syntax(), &mod_path, ctx, builder.text_edit_builder()); | 109 | insert_use_statement( |
110 | path.syntax(), | ||
111 | &mod_path.to_string(), | ||
112 | ctx, | ||
113 | builder.text_edit_builder(), | ||
114 | ); | ||
110 | } | 115 | } |
111 | Some(()) | 116 | Some(()) |
112 | } | 117 | } |
diff --git a/crates/assists/src/handlers/replace_qualified_name_with_use.rs b/crates/assists/src/handlers/replace_qualified_name_with_use.rs index 011bf1106..470e5f8ff 100644 --- a/crates/assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/assists/src/handlers/replace_qualified_name_with_use.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use hir; | 1 | use syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SyntaxNode, TextRange}; |
2 | use syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SmolStr, SyntaxNode}; | 2 | use test_utils::mark; |
3 | 3 | ||
4 | use crate::{ | 4 | use crate::{ |
5 | utils::{find_insert_use_container, insert_use_statement}, | 5 | utils::{find_insert_use_container, insert_use_statement}, |
@@ -28,12 +28,19 @@ pub(crate) fn replace_qualified_name_with_use( | |||
28 | if path.syntax().ancestors().find_map(ast::Use::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 | if path.qualifier().is_none() { | |
32 | let hir_path = ctx.sema.lower_path(&path)?; | 32 | mark::hit!(dont_import_trivial_paths); |
33 | let segments = collect_hir_path_segments(&hir_path)?; | ||
34 | if segments.len() < 2 { | ||
35 | return None; | 33 | return None; |
36 | } | 34 | } |
35 | let path_to_import = path.to_string().clone(); | ||
36 | let path_to_import = match path.segment()?.generic_arg_list() { | ||
37 | Some(generic_args) => { | ||
38 | let generic_args_start = | ||
39 | generic_args.syntax().text_range().start() - path.syntax().text_range().start(); | ||
40 | &path_to_import[TextRange::up_to(generic_args_start)] | ||
41 | } | ||
42 | None => path_to_import.as_str(), | ||
43 | }; | ||
37 | 44 | ||
38 | let target = path.syntax().text_range(); | 45 | let target = path.syntax().text_range(); |
39 | acc.add( | 46 | acc.add( |
@@ -41,12 +48,16 @@ pub(crate) fn replace_qualified_name_with_use( | |||
41 | "Replace qualified path with use", | 48 | "Replace qualified path with use", |
42 | target, | 49 | target, |
43 | |builder| { | 50 | |builder| { |
44 | let path_to_import = hir_path.mod_path().clone(); | ||
45 | let container = match find_insert_use_container(path.syntax(), ctx) { | 51 | let container = match find_insert_use_container(path.syntax(), ctx) { |
46 | Some(c) => c, | 52 | Some(c) => c, |
47 | None => return, | 53 | None => return, |
48 | }; | 54 | }; |
49 | insert_use_statement(path.syntax(), &path_to_import, ctx, builder.text_edit_builder()); | 55 | insert_use_statement( |
56 | path.syntax(), | ||
57 | &path_to_import.to_string(), | ||
58 | ctx, | ||
59 | builder.text_edit_builder(), | ||
60 | ); | ||
50 | 61 | ||
51 | // Now that we've brought the name into scope, re-qualify all paths that could be | 62 | // Now that we've brought the name into scope, re-qualify all paths that could be |
52 | // affected (that is, all paths inside the node we added the `use` to). | 63 | // affected (that is, all paths inside the node we added the `use` to). |
@@ -58,26 +69,6 @@ pub(crate) fn replace_qualified_name_with_use( | |||
58 | ) | 69 | ) |
59 | } | 70 | } |
60 | 71 | ||
61 | fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> { | ||
62 | let mut ps = Vec::<SmolStr>::with_capacity(10); | ||
63 | match path.kind() { | ||
64 | hir::PathKind::Abs => ps.push("".into()), | ||
65 | hir::PathKind::Crate => ps.push("crate".into()), | ||
66 | hir::PathKind::Plain => {} | ||
67 | hir::PathKind::Super(0) => ps.push("self".into()), | ||
68 | hir::PathKind::Super(lvl) => { | ||
69 | let mut chain = "super".to_string(); | ||
70 | for _ in 0..*lvl { | ||
71 | chain += "::super"; | ||
72 | } | ||
73 | ps.push(chain.into()); | ||
74 | } | ||
75 | hir::PathKind::DollarCrate(_) => return None, | ||
76 | } | ||
77 | ps.extend(path.segments().iter().map(|it| it.name.to_string().into())); | ||
78 | Some(ps) | ||
79 | } | ||
80 | |||
81 | /// Adds replacements to `re` that shorten `path` in all descendants of `node`. | 72 | /// Adds replacements to `re` that shorten `path` in all descendants of `node`. |
82 | fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: ast::Path) { | 73 | fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: ast::Path) { |
83 | for child in node.children() { | 74 | for child in node.children() { |
@@ -467,7 +458,8 @@ impl Debug for Foo { | |||
467 | } | 458 | } |
468 | 459 | ||
469 | #[test] | 460 | #[test] |
470 | fn test_replace_not_applicable_one_segment() { | 461 | fn dont_import_trivial_paths() { |
462 | mark::check!(dont_import_trivial_paths); | ||
471 | check_assist_not_applicable( | 463 | check_assist_not_applicable( |
472 | replace_qualified_name_with_use, | 464 | replace_qualified_name_with_use, |
473 | r" | 465 | r" |
diff --git a/crates/assists/src/lib.rs b/crates/assists/src/lib.rs index ae90d68a3..c589b08dc 100644 --- a/crates/assists/src/lib.rs +++ b/crates/assists/src/lib.rs | |||
@@ -66,13 +66,13 @@ pub struct GroupLabel(pub String); | |||
66 | 66 | ||
67 | #[derive(Debug, Clone)] | 67 | #[derive(Debug, Clone)] |
68 | pub struct Assist { | 68 | pub struct Assist { |
69 | id: AssistId, | 69 | pub id: AssistId, |
70 | /// Short description of the assist, as shown in the UI. | 70 | /// Short description of the assist, as shown in the UI. |
71 | label: String, | 71 | label: String, |
72 | group: Option<GroupLabel>, | 72 | pub group: Option<GroupLabel>, |
73 | /// Target ranges are used to sort assists: the smaller the target range, | 73 | /// Target ranges are used to sort assists: the smaller the target range, |
74 | /// the more specific assist is, and so it should be sorted first. | 74 | /// the more specific assist is, and so it should be sorted first. |
75 | target: TextRange, | 75 | pub target: TextRange, |
76 | } | 76 | } |
77 | 77 | ||
78 | #[derive(Debug, Clone)] | 78 | #[derive(Debug, Clone)] |
@@ -82,6 +82,11 @@ pub struct ResolvedAssist { | |||
82 | } | 82 | } |
83 | 83 | ||
84 | impl Assist { | 84 | impl Assist { |
85 | fn new(id: AssistId, label: String, group: Option<GroupLabel>, target: TextRange) -> Assist { | ||
86 | assert!(label.starts_with(char::is_uppercase)); | ||
87 | Assist { id, label, group, target } | ||
88 | } | ||
89 | |||
85 | /// Return all the assists applicable at the given position. | 90 | /// Return all the assists applicable at the given position. |
86 | /// | 91 | /// |
87 | /// Assists are returned in the "unresolved" state, that is only labels are | 92 | /// Assists are returned in the "unresolved" state, that is only labels are |
@@ -114,30 +119,8 @@ impl Assist { | |||
114 | acc.finish_resolved() | 119 | acc.finish_resolved() |
115 | } | 120 | } |
116 | 121 | ||
117 | pub(crate) fn new( | 122 | pub fn label(&self) -> &str { |
118 | id: AssistId, | 123 | self.label.as_str() |
119 | label: String, | ||
120 | group: Option<GroupLabel>, | ||
121 | target: TextRange, | ||
122 | ) -> Assist { | ||
123 | assert!(label.starts_with(|c: char| c.is_uppercase())); | ||
124 | Assist { id, label, group, target } | ||
125 | } | ||
126 | |||
127 | pub fn id(&self) -> AssistId { | ||
128 | self.id | ||
129 | } | ||
130 | |||
131 | pub fn label(&self) -> String { | ||
132 | self.label.clone() | ||
133 | } | ||
134 | |||
135 | pub fn group(&self) -> Option<GroupLabel> { | ||
136 | self.group.clone() | ||
137 | } | ||
138 | |||
139 | pub fn target(&self) -> TextRange { | ||
140 | self.target | ||
141 | } | 124 | } |
142 | } | 125 | } |
143 | 126 | ||
diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs index d16e6fb0a..173567003 100644 --- a/crates/assists/src/tests/generated.rs +++ b/crates/assists/src/tests/generated.rs | |||
@@ -82,8 +82,8 @@ trait Trait { | |||
82 | impl Trait for () { | 82 | impl Trait for () { |
83 | Type X = (); | 83 | Type X = (); |
84 | fn foo(&self) {} | 84 | fn foo(&self) {} |
85 | $0fn bar(&self) {} | ||
86 | 85 | ||
86 | $0fn bar(&self) {} | ||
87 | } | 87 | } |
88 | "#####, | 88 | "#####, |
89 | ) | 89 | ) |
@@ -115,7 +115,6 @@ impl Trait<u32> for () { | |||
115 | fn foo(&self) -> u32 { | 115 | fn foo(&self) -> u32 { |
116 | ${0:todo!()} | 116 | ${0:todo!()} |
117 | } | 117 | } |
118 | |||
119 | } | 118 | } |
120 | "#####, | 119 | "#####, |
121 | ) | 120 | ) |
diff --git a/crates/assists/src/utils/insert_use.rs b/crates/assists/src/utils/insert_use.rs index 50a62ee82..49096a67c 100644 --- a/crates/assists/src/utils/insert_use.rs +++ b/crates/assists/src/utils/insert_use.rs | |||
@@ -5,7 +5,6 @@ | |||
5 | use std::iter::successors; | 5 | use std::iter::successors; |
6 | 6 | ||
7 | use either::Either; | 7 | use either::Either; |
8 | use hir::{self, ModPath}; | ||
9 | use syntax::{ | 8 | use syntax::{ |
10 | ast::{self, NameOwner, VisibilityOwner}, | 9 | ast::{self, NameOwner, VisibilityOwner}, |
11 | AstNode, AstToken, Direction, SmolStr, | 10 | AstNode, AstToken, Direction, SmolStr, |
@@ -35,11 +34,11 @@ pub(crate) fn find_insert_use_container( | |||
35 | pub(crate) fn insert_use_statement( | 34 | pub(crate) fn insert_use_statement( |
36 | // Ideally the position of the cursor, used to | 35 | // Ideally the position of the cursor, used to |
37 | position: &SyntaxNode, | 36 | position: &SyntaxNode, |
38 | path_to_import: &ModPath, | 37 | path_to_import: &str, |
39 | ctx: &AssistContext, | 38 | ctx: &AssistContext, |
40 | builder: &mut TextEditBuilder, | 39 | builder: &mut TextEditBuilder, |
41 | ) { | 40 | ) { |
42 | let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::<Vec<_>>(); | 41 | let target = path_to_import.split("::").map(SmolStr::new).collect::<Vec<_>>(); |
43 | let container = find_insert_use_container(position, ctx); | 42 | let container = find_insert_use_container(position, ctx); |
44 | 43 | ||
45 | if let Some(container) = container { | 44 | if let Some(container) = container { |