diff options
author | Kirill Bulatov <[email protected]> | 2020-09-05 23:41:18 +0100 |
---|---|---|
committer | Kirill Bulatov <[email protected]> | 2020-09-09 23:42:20 +0100 |
commit | b2bcc5278db23c3ba0a4f47a3ef6ee411aaaa8dc (patch) | |
tree | a113b1ab197ca991144bb08d56cbde94d461f57b | |
parent | 486c5c3285682408b125613475a34a0bc9a2c097 (diff) |
Properly handle special cases (binaries, mod.rs)
-rw-r--r-- | crates/base_db/src/lib.rs | 24 | ||||
-rw-r--r-- | crates/ide/src/completion/completion_context.rs | 4 | ||||
-rw-r--r-- | crates/vfs/src/file_set.rs | 84 |
3 files changed, 60 insertions, 52 deletions
diff --git a/crates/base_db/src/lib.rs b/crates/base_db/src/lib.rs index c72e254f4..030b96829 100644 --- a/crates/base_db/src/lib.rs +++ b/crates/base_db/src/lib.rs | |||
@@ -167,29 +167,7 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> { | |||
167 | } | 167 | } |
168 | 168 | ||
169 | fn possible_sudmobule_names(&self, module_file: FileId) -> Vec<String> { | 169 | fn possible_sudmobule_names(&self, module_file: FileId) -> Vec<String> { |
170 | let module_files = &self.source_root(module_file).file_set; | 170 | self.source_root(module_file).file_set.possible_sudmobule_names(module_file) |
171 | let possible_submodule_files = match module_files.file_name_and_extension(module_file) { | ||
172 | Some(("mod", Some("rs"))) | Some(("lib", Some("rs"))) => { | ||
173 | module_files.list_files_with_extensions(module_file, None) | ||
174 | } | ||
175 | // TODO kb for `src/bin/foo.rs`, we need to check for modules in `src/bin/` | ||
176 | Some((directory_with_module_name, Some("rs"))) => module_files | ||
177 | .list_files_with_extensions( | ||
178 | module_file, | ||
179 | Some(&format!("../{}/", directory_with_module_name)), | ||
180 | ), | ||
181 | // TODO kb also consider the case when there's no `../module_name.rs`, but `../module_name/mod.rs` | ||
182 | _ => Vec::new(), | ||
183 | }; | ||
184 | |||
185 | possible_submodule_files | ||
186 | .into_iter() | ||
187 | .filter(|(_, extension)| extension == &Some("rs")) | ||
188 | .filter(|(file_name, _)| file_name != &"mod") | ||
189 | .filter(|(file_name, _)| file_name != &"lib") | ||
190 | .filter(|(file_name, _)| file_name != &"main") | ||
191 | .map(|(file_name, _)| file_name.to_owned()) | ||
192 | .collect() | ||
193 | } | 171 | } |
194 | } | 172 | } |
195 | 173 | ||
diff --git a/crates/ide/src/completion/completion_context.rs b/crates/ide/src/completion/completion_context.rs index 74cd16e0a..a8fe44083 100644 --- a/crates/ide/src/completion/completion_context.rs +++ b/crates/ide/src/completion/completion_context.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use base_db::{FileLoader, SourceDatabase}; | 3 | use base_db::{FileLoader, SourceDatabase}; |
4 | use hir::{ModuleSource, Semantics, SemanticsScope, Type}; | 4 | use hir::{Semantics, SemanticsScope, Type}; |
5 | use ide_db::RootDatabase; | 5 | use ide_db::RootDatabase; |
6 | use syntax::{ | 6 | use syntax::{ |
7 | algo::{find_covering_element, find_node_at_offset}, | 7 | algo::{find_covering_element, find_node_at_offset}, |
@@ -123,11 +123,9 @@ impl<'a> CompletionContext<'a> { | |||
123 | dbg!(mod_declaration_candidates); | 123 | dbg!(mod_declaration_candidates); |
124 | // TODO kb exlude existing children from the candidates | 124 | // TODO kb exlude existing children from the candidates |
125 | let existing_children = current_module.children(db).collect::<Vec<_>>(); | 125 | let existing_children = current_module.children(db).collect::<Vec<_>>(); |
126 | dbg!(existing_children); | ||
127 | None::<Vec<String>> | 126 | None::<Vec<String>> |
128 | }) | 127 | }) |
129 | .unwrap_or_default(); | 128 | .unwrap_or_default(); |
130 | dbg!(module_names_for_import); | ||
131 | }; | 129 | }; |
132 | 130 | ||
133 | let krate = sema.to_module_def(position.file_id).map(|m| m.krate()); | 131 | let krate = sema.to_module_def(position.file_id).map(|m| m.krate()); |
diff --git a/crates/vfs/src/file_set.rs b/crates/vfs/src/file_set.rs index 3085fd818..cb65c17e0 100644 --- a/crates/vfs/src/file_set.rs +++ b/crates/vfs/src/file_set.rs | |||
@@ -26,38 +26,70 @@ impl FileSet { | |||
26 | self.files.get(&path).copied() | 26 | self.files.get(&path).copied() |
27 | } | 27 | } |
28 | 28 | ||
29 | pub fn file_name_and_extension(&self, file: FileId) -> Option<(&str, Option<&str>)> { | 29 | pub fn possible_sudmobule_names(&self, module_file: FileId) -> Vec<String> { |
30 | self.paths[&file].file_name_and_extension() | 30 | let directory_to_look_for_submodules = match self.get_directory_with_submodules(module_file) |
31 | } | 31 | { |
32 | 32 | Some(directory) => directory, | |
33 | pub fn list_files_with_extensions( | 33 | None => return Vec::new(), |
34 | &self, | ||
35 | anchor: FileId, | ||
36 | anchor_relative_path: Option<&str>, | ||
37 | ) -> Vec<(&str, Option<&str>)> { | ||
38 | let anchor_directory = { | ||
39 | let path = self.paths[&anchor].clone(); | ||
40 | match anchor_relative_path { | ||
41 | Some(anchor_relative_path) => path.join(anchor_relative_path), | ||
42 | None => path.parent(), | ||
43 | } | ||
44 | }; | 34 | }; |
45 | 35 | self.paths | |
46 | if let Some(anchor_directory) = anchor_directory { | 36 | .iter() |
47 | self.paths | 37 | .filter_map(|(_, path)| { |
48 | .iter() | 38 | if path.parent()? == directory_to_look_for_submodules { |
49 | .filter_map(|(_, path)| { | 39 | path.file_name_and_extension() |
50 | if path.parent()? == anchor_directory { | 40 | } else { |
51 | path.file_name_and_extension() | 41 | None |
42 | } | ||
43 | }) | ||
44 | .filter_map(|file_name_and_extension| match file_name_and_extension { | ||
45 | // TODO kb do not include the module file name itself, if present | ||
46 | // TODO kb wrong resolution for nesСпаted non-file modules (mod tests {mod <|>) | ||
47 | // TODO kb in src/bin when a module is included into another, | ||
48 | // the included file gets "moved" into a directory below and now cannot add any other modules | ||
49 | ("mod", Some("rs")) | ("lib", Some("rs")) | ("main", Some("rs")) => None, | ||
50 | (file_name, Some("rs")) => Some(file_name.to_owned()), | ||
51 | (subdirectory_name, None) => { | ||
52 | let mod_rs_path = | ||
53 | directory_to_look_for_submodules.join(subdirectory_name)?.join("mod.rs")?; | ||
54 | if self.files.contains_key(&mod_rs_path) { | ||
55 | Some(subdirectory_name.to_owned()) | ||
52 | } else { | 56 | } else { |
53 | None | 57 | None |
54 | } | 58 | } |
55 | }) | 59 | } |
56 | .collect() | 60 | _ => None, |
57 | } else { | 61 | }) |
58 | Vec::new() | 62 | .collect() |
63 | } | ||
64 | |||
65 | fn get_directory_with_submodules(&self, module_file: FileId) -> Option<VfsPath> { | ||
66 | let module_file_path = &self.paths[&module_file]; | ||
67 | let module_directory_path = module_file_path.parent()?; | ||
68 | match module_file_path.file_name_and_extension() { | ||
69 | Some(("mod", Some("rs"))) | Some(("lib", Some("rs"))) | Some(("main", Some("rs"))) => { | ||
70 | Some(module_directory_path) | ||
71 | } | ||
72 | Some((regular_rust_file_name, Some("rs"))) => { | ||
73 | if matches!( | ||
74 | ( | ||
75 | module_directory_path | ||
76 | .parent() | ||
77 | .as_ref() | ||
78 | .and_then(|path| path.file_name_and_extension()), | ||
79 | module_directory_path.file_name_and_extension(), | ||
80 | ), | ||
81 | (Some(("src", None)), Some(("bin", None))) | ||
82 | ) { | ||
83 | // files in /src/bin/ can import each other directly | ||
84 | Some(module_directory_path) | ||
85 | } else { | ||
86 | module_directory_path.join(regular_rust_file_name) | ||
87 | } | ||
88 | } | ||
89 | _ => None, | ||
59 | } | 90 | } |
60 | } | 91 | } |
92 | |||
61 | pub fn insert(&mut self, file_id: FileId, path: VfsPath) { | 93 | pub fn insert(&mut self, file_id: FileId, path: VfsPath) { |
62 | self.files.insert(path.clone(), file_id); | 94 | self.files.insert(path.clone(), file_id); |
63 | self.paths.insert(file_id, path); | 95 | self.paths.insert(file_id, path); |