diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/assists/src/handlers/auto_import.rs | 3 | ||||
-rw-r--r-- | crates/assists/src/handlers/extract_struct_from_enum_variant.rs | 3 | ||||
-rw-r--r-- | crates/assists/src/handlers/replace_qualified_name_with_use.rs | 2 | ||||
-rw-r--r-- | crates/assists/src/utils.rs | 3 | ||||
-rw-r--r-- | crates/assists/src/utils/insert_use.rs | 14 | ||||
-rw-r--r-- | crates/completion/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/completion/src/completions.rs | 1 | ||||
-rw-r--r-- | crates/completion/src/completions/complete_magic.rs | 114 | ||||
-rw-r--r-- | crates/completion/src/item.rs | 1 | ||||
-rw-r--r-- | crates/completion/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/hir/src/code_model.rs | 10 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ide_db/src/imports_locator.rs | 14 |
13 files changed, 144 insertions, 25 deletions
diff --git a/crates/assists/src/handlers/auto_import.rs b/crates/assists/src/handlers/auto_import.rs index 37dd61266..d665837a2 100644 --- a/crates/assists/src/handlers/auto_import.rs +++ b/crates/assists/src/handlers/auto_import.rs | |||
@@ -98,7 +98,8 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
98 | 98 | ||
99 | let range = ctx.sema.original_range(import_assets.syntax_under_caret()).range; | 99 | let range = ctx.sema.original_range(import_assets.syntax_under_caret()).range; |
100 | let group = import_group_message(import_assets.import_candidate()); | 100 | let group = import_group_message(import_assets.import_candidate()); |
101 | let scope = ImportScope::find_insert_use_container(import_assets.syntax_under_caret(), ctx)?; | 101 | let scope = |
102 | ImportScope::find_insert_use_container(import_assets.syntax_under_caret(), &ctx.sema)?; | ||
102 | for (import, _) in proposed_imports { | 103 | for (import, _) in proposed_imports { |
103 | acc.add_group( | 104 | acc.add_group( |
104 | &group, | 105 | &group, |
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 067afabf2..cac77c49b 100644 --- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs | |||
@@ -143,8 +143,7 @@ fn insert_import( | |||
143 | if let Some(mut mod_path) = mod_path { | 143 | if let Some(mut mod_path) = mod_path { |
144 | mod_path.segments.pop(); | 144 | mod_path.segments.pop(); |
145 | mod_path.segments.push(variant_hir_name.clone()); | 145 | mod_path.segments.push(variant_hir_name.clone()); |
146 | let scope = ImportScope::find_insert_use_container(scope_node, ctx)?; | 146 | let scope = ImportScope::find_insert_use_container(scope_node, &ctx.sema)?; |
147 | |||
148 | *rewriter += insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use.merge); | 147 | *rewriter += insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use.merge); |
149 | } | 148 | } |
150 | Some(()) | 149 | Some(()) |
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 d7e1d9580..a66db9ae3 100644 --- a/crates/assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/assists/src/handlers/replace_qualified_name_with_use.rs | |||
@@ -34,7 +34,7 @@ pub(crate) fn replace_qualified_name_with_use( | |||
34 | } | 34 | } |
35 | 35 | ||
36 | let target = path.syntax().text_range(); | 36 | let target = path.syntax().text_range(); |
37 | let scope = ImportScope::find_insert_use_container(path.syntax(), ctx)?; | 37 | let scope = ImportScope::find_insert_use_container(path.syntax(), &ctx.sema)?; |
38 | let syntax = scope.as_syntax_node(); | 38 | let syntax = scope.as_syntax_node(); |
39 | acc.add( | 39 | acc.add( |
40 | AssistId("replace_qualified_name_with_use", AssistKind::RefactorRewrite), | 40 | AssistId("replace_qualified_name_with_use", AssistKind::RefactorRewrite), |
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs index 7bd338e99..caabc44de 100644 --- a/crates/assists/src/utils.rs +++ b/crates/assists/src/utils.rs | |||
@@ -21,8 +21,7 @@ use crate::{ | |||
21 | ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, | 21 | ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, |
22 | }; | 22 | }; |
23 | 23 | ||
24 | pub use insert_use::MergeBehaviour; | 24 | pub use insert_use::{insert_use, ImportScope, MergeBehaviour}; |
25 | pub(crate) use insert_use::{insert_use, ImportScope}; | ||
26 | 25 | ||
27 | pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path { | 26 | pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path { |
28 | let mut segments = Vec::new(); | 27 | let mut segments = Vec::new(); |
diff --git a/crates/assists/src/utils/insert_use.rs b/crates/assists/src/utils/insert_use.rs index af3fc96b6..1aa727e11 100644 --- a/crates/assists/src/utils/insert_use.rs +++ b/crates/assists/src/utils/insert_use.rs | |||
@@ -1,6 +1,8 @@ | |||
1 | //! Handle syntactic aspects of inserting a new `use`. | 1 | //! Handle syntactic aspects of inserting a new `use`. |
2 | use std::{cmp::Ordering, iter::successors}; | 2 | use std::{cmp::Ordering, iter::successors}; |
3 | 3 | ||
4 | use hir::Semantics; | ||
5 | use ide_db::RootDatabase; | ||
4 | use itertools::{EitherOrBoth, Itertools}; | 6 | use itertools::{EitherOrBoth, Itertools}; |
5 | use syntax::{ | 7 | use syntax::{ |
6 | algo::SyntaxRewriter, | 8 | algo::SyntaxRewriter, |
@@ -14,7 +16,7 @@ use syntax::{ | |||
14 | use test_utils::mark; | 16 | use test_utils::mark; |
15 | 17 | ||
16 | #[derive(Debug)] | 18 | #[derive(Debug)] |
17 | pub(crate) enum ImportScope { | 19 | pub enum ImportScope { |
18 | File(ast::SourceFile), | 20 | File(ast::SourceFile), |
19 | Module(ast::ItemList), | 21 | Module(ast::ItemList), |
20 | } | 22 | } |
@@ -31,14 +33,14 @@ impl ImportScope { | |||
31 | } | 33 | } |
32 | 34 | ||
33 | /// Determines the containing syntax node in which to insert a `use` statement affecting `position`. | 35 | /// Determines the containing syntax node in which to insert a `use` statement affecting `position`. |
34 | pub(crate) fn find_insert_use_container( | 36 | pub fn find_insert_use_container( |
35 | position: &SyntaxNode, | 37 | position: &SyntaxNode, |
36 | ctx: &crate::assist_context::AssistContext, | 38 | sema: &Semantics<'_, RootDatabase>, |
37 | ) -> Option<Self> { | 39 | ) -> Option<Self> { |
38 | ctx.sema.ancestors_with_macros(position.clone()).find_map(Self::from) | 40 | sema.ancestors_with_macros(position.clone()).find_map(Self::from) |
39 | } | 41 | } |
40 | 42 | ||
41 | pub(crate) fn as_syntax_node(&self) -> &SyntaxNode { | 43 | pub fn as_syntax_node(&self) -> &SyntaxNode { |
42 | match self { | 44 | match self { |
43 | ImportScope::File(file) => file.syntax(), | 45 | ImportScope::File(file) => file.syntax(), |
44 | ImportScope::Module(item_list) => item_list.syntax(), | 46 | ImportScope::Module(item_list) => item_list.syntax(), |
@@ -88,7 +90,7 @@ fn is_inner_comment(token: SyntaxToken) -> bool { | |||
88 | } | 90 | } |
89 | 91 | ||
90 | /// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur. | 92 | /// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur. |
91 | pub(crate) fn insert_use<'a>( | 93 | pub fn insert_use<'a>( |
92 | scope: &ImportScope, | 94 | scope: &ImportScope, |
93 | path: ast::Path, | 95 | path: ast::Path, |
94 | merge: Option<MergeBehaviour>, | 96 | merge: Option<MergeBehaviour>, |
diff --git a/crates/completion/Cargo.toml b/crates/completion/Cargo.toml index 3015ec9e0..799b4a3d5 100644 --- a/crates/completion/Cargo.toml +++ b/crates/completion/Cargo.toml | |||
@@ -13,6 +13,7 @@ doctest = false | |||
13 | itertools = "0.9.0" | 13 | itertools = "0.9.0" |
14 | log = "0.4.8" | 14 | log = "0.4.8" |
15 | rustc-hash = "1.1.0" | 15 | rustc-hash = "1.1.0" |
16 | either = "1.6.1" | ||
16 | 17 | ||
17 | assists = { path = "../assists", version = "0.0.0" } | 18 | assists = { path = "../assists", version = "0.0.0" } |
18 | stdx = { path = "../stdx", version = "0.0.0" } | 19 | stdx = { path = "../stdx", version = "0.0.0" } |
@@ -21,6 +22,7 @@ text_edit = { path = "../text_edit", version = "0.0.0" } | |||
21 | base_db = { path = "../base_db", version = "0.0.0" } | 22 | base_db = { path = "../base_db", version = "0.0.0" } |
22 | ide_db = { path = "../ide_db", version = "0.0.0" } | 23 | ide_db = { path = "../ide_db", version = "0.0.0" } |
23 | profile = { path = "../profile", version = "0.0.0" } | 24 | profile = { path = "../profile", version = "0.0.0" } |
25 | assists = { path = "../assists", version = "0.0.0" } | ||
24 | test_utils = { path = "../test_utils", version = "0.0.0" } | 26 | test_utils = { path = "../test_utils", version = "0.0.0" } |
25 | 27 | ||
26 | # completions crate should depend only on the top-level `hir` package. if you need | 28 | # completions crate should depend only on the top-level `hir` package. if you need |
diff --git a/crates/completion/src/completions.rs b/crates/completion/src/completions.rs index 75dbb1a23..99db5f998 100644 --- a/crates/completion/src/completions.rs +++ b/crates/completion/src/completions.rs | |||
@@ -13,6 +13,7 @@ pub(crate) mod postfix; | |||
13 | pub(crate) mod macro_in_item_position; | 13 | pub(crate) mod macro_in_item_position; |
14 | pub(crate) mod trait_impl; | 14 | pub(crate) mod trait_impl; |
15 | pub(crate) mod mod_; | 15 | pub(crate) mod mod_; |
16 | pub(crate) mod complete_magic; | ||
16 | 17 | ||
17 | use hir::{ModPath, ScopeDef, Type}; | 18 | use hir::{ModPath, ScopeDef, Type}; |
18 | 19 | ||
diff --git a/crates/completion/src/completions/complete_magic.rs b/crates/completion/src/completions/complete_magic.rs new file mode 100644 index 000000000..857a0b620 --- /dev/null +++ b/crates/completion/src/completions/complete_magic.rs | |||
@@ -0,0 +1,114 @@ | |||
1 | //! TODO kb move this into the complete_unqualified_path when starts to work properly | ||
2 | |||
3 | use assists::utils::{insert_use, mod_path_to_ast, ImportScope, MergeBehaviour}; | ||
4 | use hir::Query; | ||
5 | use itertools::Itertools; | ||
6 | use syntax::AstNode; | ||
7 | use text_edit::TextEdit; | ||
8 | |||
9 | use crate::{context::CompletionContext, item::CompletionKind, CompletionItem, CompletionItemKind}; | ||
10 | |||
11 | use super::Completions; | ||
12 | |||
13 | pub(crate) fn complete_magic(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { | ||
14 | if !(ctx.is_trivial_path || ctx.is_pat_binding_or_const) { | ||
15 | return None; | ||
16 | } | ||
17 | let current_module = ctx.scope.module()?; | ||
18 | let anchor = ctx.name_ref_syntax.as_ref()?; | ||
19 | let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?; | ||
20 | // TODO kb now this is the whole file, which is not disjoint with any other change in the same file, fix it | ||
21 | // otherwise it's impossible to correctly add the use statement and also change the completed text into something more meaningful | ||
22 | let import_syntax = import_scope.as_syntax_node(); | ||
23 | |||
24 | // TODO kb consider heuristics, such as "don't show `hash_map` import if `HashMap` is the import for completion" | ||
25 | // TODO kb module functions are not completed, consider `std::io::stdin` one | ||
26 | let potential_import_name = ctx.token.to_string(); | ||
27 | |||
28 | let possible_imports = ctx | ||
29 | .krate? | ||
30 | // TODO kb use imports_locator instead? | ||
31 | .query_external_importables(ctx.db, Query::new(&potential_import_name).limit(40)) | ||
32 | .unique() | ||
33 | .filter_map(|import_candidate| match import_candidate { | ||
34 | either::Either::Left(module_def) => current_module.find_use_path(ctx.db, module_def), | ||
35 | either::Either::Right(macro_def) => current_module.find_use_path(ctx.db, macro_def), | ||
36 | }) | ||
37 | .filter_map(|mod_path| { | ||
38 | let correct_qualifier = mod_path.segments.last()?.to_string(); | ||
39 | let rewriter = | ||
40 | insert_use(&import_scope, mod_path_to_ast(&mod_path), Some(MergeBehaviour::Full)); | ||
41 | let rewritten_node = rewriter.rewrite(import_syntax); | ||
42 | let insert_use_edit = | ||
43 | TextEdit::replace(import_syntax.text_range(), rewritten_node.to_string()); | ||
44 | let mut completion_edit = | ||
45 | TextEdit::replace(anchor.syntax().text_range(), correct_qualifier); | ||
46 | completion_edit.union(insert_use_edit).expect("TODO kb"); | ||
47 | |||
48 | let completion_item: CompletionItem = CompletionItem::new( | ||
49 | CompletionKind::Magic, | ||
50 | ctx.source_range(), | ||
51 | mod_path.to_string(), | ||
52 | ) | ||
53 | .kind(CompletionItemKind::Struct) | ||
54 | .text_edit(completion_edit) | ||
55 | .into(); | ||
56 | Some(completion_item) | ||
57 | }); | ||
58 | acc.add_all(possible_imports); | ||
59 | |||
60 | Some(()) | ||
61 | } | ||
62 | |||
63 | #[cfg(test)] | ||
64 | mod tests { | ||
65 | use expect_test::{expect, Expect}; | ||
66 | |||
67 | use crate::{ | ||
68 | item::CompletionKind, | ||
69 | test_utils::{check_edit, completion_list}, | ||
70 | }; | ||
71 | |||
72 | fn check(ra_fixture: &str, expect: Expect) { | ||
73 | let actual = completion_list(ra_fixture, CompletionKind::Magic); | ||
74 | expect.assert_eq(&actual) | ||
75 | } | ||
76 | |||
77 | #[test] | ||
78 | fn case_insensitive_magic_completion_works() { | ||
79 | check( | ||
80 | r#" | ||
81 | //- /lib.rs crate:dep | ||
82 | pub struct TestStruct; | ||
83 | |||
84 | //- /main.rs crate:main deps:dep | ||
85 | fn main() { | ||
86 | teru<|> | ||
87 | } | ||
88 | "#, | ||
89 | expect![[r#" | ||
90 | st dep::TestStruct | ||
91 | "#]], | ||
92 | ); | ||
93 | |||
94 | check_edit( | ||
95 | "dep::TestStruct", | ||
96 | r#" | ||
97 | //- /lib.rs crate:dep | ||
98 | pub struct TestStruct; | ||
99 | |||
100 | //- /main.rs crate:main deps:dep | ||
101 | fn main() { | ||
102 | teru<|> | ||
103 | } | ||
104 | "#, | ||
105 | r#" | ||
106 | use dep::TestStruct; | ||
107 | |||
108 | fn main() { | ||
109 | TestStruct | ||
110 | } | ||
111 | "#, | ||
112 | ); | ||
113 | } | ||
114 | } | ||
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs index 6d1d085f4..f23913935 100644 --- a/crates/completion/src/item.rs +++ b/crates/completion/src/item.rs | |||
@@ -31,6 +31,7 @@ pub struct CompletionItem { | |||
31 | /// | 31 | /// |
32 | /// Typically, replaces `source_range` with new identifier. | 32 | /// Typically, replaces `source_range` with new identifier. |
33 | text_edit: TextEdit, | 33 | text_edit: TextEdit, |
34 | |||
34 | insert_text_format: InsertTextFormat, | 35 | insert_text_format: InsertTextFormat, |
35 | 36 | ||
36 | /// What item (struct, function, etc) are we completing. | 37 | /// What item (struct, function, etc) are we completing. |
diff --git a/crates/completion/src/lib.rs b/crates/completion/src/lib.rs index cb6e0554e..e920fa6b5 100644 --- a/crates/completion/src/lib.rs +++ b/crates/completion/src/lib.rs | |||
@@ -118,6 +118,7 @@ pub fn completions( | |||
118 | completions::macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); | 118 | completions::macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); |
119 | completions::trait_impl::complete_trait_impl(&mut acc, &ctx); | 119 | completions::trait_impl::complete_trait_impl(&mut acc, &ctx); |
120 | completions::mod_::complete_mod(&mut acc, &ctx); | 120 | completions::mod_::complete_mod(&mut acc, &ctx); |
121 | completions::complete_magic::complete_magic(&mut acc, &ctx); | ||
121 | 122 | ||
122 | Some(acc) | 123 | Some(acc) |
123 | } | 124 | } |
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 30a5e4580..37ed092ad 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -110,15 +110,9 @@ impl Crate { | |||
110 | pub fn query_external_importables( | 110 | pub fn query_external_importables( |
111 | self, | 111 | self, |
112 | db: &dyn DefDatabase, | 112 | db: &dyn DefDatabase, |
113 | query: &str, | 113 | query: import_map::Query, |
114 | ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { | 114 | ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { |
115 | import_map::search_dependencies( | 115 | import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| match item { |
116 | db, | ||
117 | self.into(), | ||
118 | import_map::Query::new(query).anchor_end().case_sensitive().limit(40), | ||
119 | ) | ||
120 | .into_iter() | ||
121 | .map(|item| match item { | ||
122 | ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()), | 116 | ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()), |
123 | ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()), | 117 | ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()), |
124 | }) | 118 | }) |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 0d184379f..ad58a7cfe 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -49,6 +49,7 @@ pub use hir_def::{ | |||
49 | builtin_type::BuiltinType, | 49 | builtin_type::BuiltinType, |
50 | docs::Documentation, | 50 | docs::Documentation, |
51 | find_path::PrefixKind, | 51 | find_path::PrefixKind, |
52 | import_map::Query, | ||
52 | item_scope::ItemInNs, | 53 | item_scope::ItemInNs, |
53 | nameres::ModuleSource, | 54 | nameres::ModuleSource, |
54 | path::{ModPath, PathKind}, | 55 | path::{ModPath, PathKind}, |
diff --git a/crates/ide_db/src/imports_locator.rs b/crates/ide_db/src/imports_locator.rs index df74be00b..e4f4b5427 100644 --- a/crates/ide_db/src/imports_locator.rs +++ b/crates/ide_db/src/imports_locator.rs | |||
@@ -1,12 +1,12 @@ | |||
1 | //! This module contains an import search funcionality that is provided to the assists module. | 1 | //! This module contains an import search funcionality that is provided to the assists module. |
2 | //! Later, this should be moved away to a separate crate that is accessible from the assists module. | 2 | //! Later, this should be moved away to a separate crate that is accessible from the assists module. |
3 | 3 | ||
4 | use hir::{Crate, MacroDef, ModuleDef, Semantics}; | 4 | use hir::{Crate, MacroDef, ModuleDef, Query as ImportMapQuery, Semantics}; |
5 | use syntax::{ast, AstNode, SyntaxKind::NAME}; | 5 | use syntax::{ast, AstNode, SyntaxKind::NAME}; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | defs::{Definition, NameClass}, | 8 | defs::{Definition, NameClass}, |
9 | symbol_index::{self, FileSymbol, Query}, | 9 | symbol_index::{self, FileSymbol, Query as SymbolQuery}, |
10 | RootDatabase, | 10 | RootDatabase, |
11 | }; | 11 | }; |
12 | use either::Either; | 12 | use either::Either; |
@@ -21,12 +21,16 @@ pub fn find_imports<'a>( | |||
21 | let db = sema.db; | 21 | let db = sema.db; |
22 | 22 | ||
23 | // Query dependencies first. | 23 | // Query dependencies first. |
24 | let mut candidates: FxHashSet<_> = | 24 | let mut candidates: FxHashSet<_> = krate |
25 | krate.query_external_importables(db, name_to_import).collect(); | 25 | .query_external_importables( |
26 | db, | ||
27 | ImportMapQuery::new(name_to_import).anchor_end().case_sensitive().limit(40), | ||
28 | ) | ||
29 | .collect(); | ||
26 | 30 | ||
27 | // Query the local crate using the symbol index. | 31 | // Query the local crate using the symbol index. |
28 | let local_results = { | 32 | let local_results = { |
29 | let mut query = Query::new(name_to_import.to_string()); | 33 | let mut query = SymbolQuery::new(name_to_import.to_string()); |
30 | query.exact(); | 34 | query.exact(); |
31 | query.limit(40); | 35 | query.limit(40); |
32 | symbol_index::crate_symbols(db, krate.into(), query) | 36 | symbol_index::crate_symbols(db, krate.into(), query) |