diff options
Diffstat (limited to 'crates/ide')
-rw-r--r-- | crates/ide/src/completion/complete_mod.rs | 103 |
1 files changed, 59 insertions, 44 deletions
diff --git a/crates/ide/src/completion/complete_mod.rs b/crates/ide/src/completion/complete_mod.rs index def8b8968..c5757a310 100644 --- a/crates/ide/src/completion/complete_mod.rs +++ b/crates/ide/src/completion/complete_mod.rs | |||
@@ -3,6 +3,7 @@ | |||
3 | use base_db::{SourceDatabaseExt, VfsPath}; | 3 | use base_db::{SourceDatabaseExt, VfsPath}; |
4 | use hir::{Module, ModuleSource}; | 4 | use hir::{Module, ModuleSource}; |
5 | use ide_db::RootDatabase; | 5 | use ide_db::RootDatabase; |
6 | use rustc_hash::FxHashSet; | ||
6 | 7 | ||
7 | use super::{completion_context::CompletionContext, completion_item::Completions}; | 8 | use super::{completion_context::CompletionContext, completion_item::Completions}; |
8 | 9 | ||
@@ -10,84 +11,98 @@ use super::{completion_context::CompletionContext, completion_item::Completions} | |||
10 | pub(super) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { | 11 | pub(super) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { |
11 | let current_module = ctx.scope.module()?; | 12 | let current_module = ctx.scope.module()?; |
12 | 13 | ||
13 | // TODO kb filter out declarations in possible_sudmobule_names | 14 | let module_definition_file = |
14 | // let declaration_source = current_module.declaration_source(ctx.db); | ||
15 | let module_definition_source_file = | ||
16 | current_module.definition_source(ctx.db).file_id.original_file(ctx.db); | 15 | current_module.definition_source(ctx.db).file_id.original_file(ctx.db); |
17 | let source_root = ctx.db.source_root(ctx.db.file_source_root(module_definition_source_file)); | 16 | let source_root = ctx.db.source_root(ctx.db.file_source_root(module_definition_file)); |
18 | let directory_to_look_for_submodules = directory_to_look_for_submodules( | 17 | let directory_to_look_for_submodules = directory_to_look_for_submodules( |
19 | current_module, | 18 | current_module, |
20 | ctx.db, | 19 | ctx.db, |
21 | source_root.path_for_file(&module_definition_source_file)?, | 20 | source_root.path_for_file(&module_definition_file)?, |
22 | )?; | 21 | )?; |
23 | 22 | ||
23 | let existing_mod_declarations = current_module | ||
24 | .children(ctx.db) | ||
25 | .filter_map(|module| Some(module.name(ctx.db)?.to_string())) | ||
26 | .collect::<FxHashSet<_>>(); | ||
27 | |||
28 | let module_declaration_file = | ||
29 | current_module.declaration_source(ctx.db).map(|module_declaration_source_file| { | ||
30 | module_declaration_source_file.file_id.original_file(ctx.db) | ||
31 | }); | ||
32 | |||
24 | let mod_declaration_candidates = source_root | 33 | let mod_declaration_candidates = source_root |
25 | .iter() | 34 | .iter() |
26 | .filter(|submodule_file| submodule_file != &module_definition_source_file) | 35 | .filter(|submodule_candidate_file| submodule_candidate_file != &module_definition_file) |
36 | .filter(|submodule_candidate_file| { | ||
37 | Some(submodule_candidate_file) != module_declaration_file.as_ref() | ||
38 | }) | ||
27 | .filter_map(|submodule_file| { | 39 | .filter_map(|submodule_file| { |
28 | let submodule_path = source_root.path_for_file(&submodule_file)?; | 40 | let submodule_path = source_root.path_for_file(&submodule_file)?; |
29 | if submodule_path.parent()? == directory_to_look_for_submodules { | 41 | if !is_special_rust_file_path(&submodule_path) |
42 | && submodule_path.parent()? == directory_to_look_for_submodules | ||
43 | { | ||
30 | submodule_path.file_name_and_extension() | 44 | submodule_path.file_name_and_extension() |
31 | } else { | 45 | } else { |
32 | None | 46 | None |
33 | } | 47 | } |
34 | }) | 48 | }) |
35 | .filter_map(|file_name_and_extension| { | 49 | .filter_map(|submodule_file_name_and_extension| match submodule_file_name_and_extension { |
36 | match file_name_and_extension { | 50 | (file_name, Some("rs")) => Some(file_name.to_owned()), |
37 | // TODO kb in src/bin when a module is included into another, | 51 | (subdirectory_name, None) => { |
38 | // the included file gets "moved" into a directory below and now cannot add any other modules | 52 | let mod_rs_path = |
39 | ("mod", Some("rs")) | ("lib", Some("rs")) | ("main", Some("rs")) => None, | 53 | directory_to_look_for_submodules.join(subdirectory_name)?.join("mod.rs")?; |
40 | (file_name, Some("rs")) => Some(file_name.to_owned()), | 54 | if source_root.file_for_path(&mod_rs_path).is_some() { |
41 | (subdirectory_name, None) => { | 55 | Some(subdirectory_name.to_owned()) |
42 | let mod_rs_path = | 56 | } else { |
43 | directory_to_look_for_submodules.join(subdirectory_name)?.join("mod.rs")?; | 57 | None |
44 | if source_root.file_for_path(&mod_rs_path).is_some() { | ||
45 | Some(subdirectory_name.to_owned()) | ||
46 | } else { | ||
47 | None | ||
48 | } | ||
49 | } | 58 | } |
50 | _ => None, | ||
51 | } | 59 | } |
60 | _ => None, | ||
52 | }) | 61 | }) |
62 | .filter(|name| !existing_mod_declarations.contains(name)) | ||
53 | .collect::<Vec<_>>(); | 63 | .collect::<Vec<_>>(); |
54 | dbg!(mod_declaration_candidates); | 64 | dbg!(mod_declaration_candidates); |
55 | 65 | ||
56 | // TODO kb exlude existing children from the candidates | 66 | // TODO kb exlude existing children from the candidates |
57 | let existing_children = current_module.children(ctx.db).collect::<Vec<_>>(); | ||
58 | 67 | ||
59 | Some(()) | 68 | Some(()) |
60 | } | 69 | } |
61 | 70 | ||
71 | fn is_special_rust_file_path(path: &VfsPath) -> bool { | ||
72 | matches!( | ||
73 | path.file_name_and_extension(), | ||
74 | Some(("mod", Some("rs"))) | Some(("lib", Some("rs"))) | Some(("main", Some("rs"))) | ||
75 | ) | ||
76 | } | ||
77 | |||
62 | fn directory_to_look_for_submodules( | 78 | fn directory_to_look_for_submodules( |
63 | module: Module, | 79 | module: Module, |
64 | db: &RootDatabase, | 80 | db: &RootDatabase, |
65 | module_file_path: &VfsPath, | 81 | module_file_path: &VfsPath, |
66 | ) -> Option<VfsPath> { | 82 | ) -> Option<VfsPath> { |
67 | let module_directory_path = module_file_path.parent()?; | 83 | let module_directory_path = module_file_path.parent()?; |
68 | 84 | let base_directory = if is_special_rust_file_path(module_file_path) { | |
69 | let base_directory = match module_file_path.file_name_and_extension()? { | 85 | Some(module_directory_path) |
70 | ("mod", Some("rs")) | ("lib", Some("rs")) | ("main", Some("rs")) => { | 86 | } else if let (regular_rust_file_name, Some("rs")) = |
87 | module_file_path.file_name_and_extension()? | ||
88 | { | ||
89 | if matches!( | ||
90 | ( | ||
91 | module_directory_path | ||
92 | .parent() | ||
93 | .as_ref() | ||
94 | .and_then(|path| path.file_name_and_extension()), | ||
95 | module_directory_path.file_name_and_extension(), | ||
96 | ), | ||
97 | (Some(("src", None)), Some(("bin", None))) | ||
98 | ) { | ||
99 | // files in /src/bin/ can import each other directly | ||
71 | Some(module_directory_path) | 100 | Some(module_directory_path) |
101 | } else { | ||
102 | module_directory_path.join(regular_rust_file_name) | ||
72 | } | 103 | } |
73 | (regular_rust_file_name, Some("rs")) => { | 104 | } else { |
74 | if matches!( | 105 | None |
75 | ( | ||
76 | module_directory_path | ||
77 | .parent() | ||
78 | .as_ref() | ||
79 | .and_then(|path| path.file_name_and_extension()), | ||
80 | module_directory_path.file_name_and_extension(), | ||
81 | ), | ||
82 | (Some(("src", None)), Some(("bin", None))) | ||
83 | ) { | ||
84 | // files in /src/bin/ can import each other directly | ||
85 | Some(module_directory_path) | ||
86 | } else { | ||
87 | module_directory_path.join(regular_rust_file_name) | ||
88 | } | ||
89 | } | ||
90 | _ => None, | ||
91 | }?; | 106 | }?; |
92 | 107 | ||
93 | let mut resulting_path = base_directory; | 108 | let mut resulting_path = base_directory; |