aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis')
-rw-r--r--crates/ra_analysis/src/completion/mod.rs7
-rw-r--r--crates/ra_analysis/src/completion/reference_completion.rs14
-rw-r--r--crates/ra_analysis/src/db.rs9
-rw-r--r--crates/ra_analysis/src/imp.rs70
-rw-r--r--crates/ra_analysis/src/lib.rs2
-rw-r--r--crates/ra_analysis/tests/tests.rs17
6 files changed, 74 insertions, 45 deletions
diff --git a/crates/ra_analysis/src/completion/mod.rs b/crates/ra_analysis/src/completion/mod.rs
index e5ba92acd..0f154112a 100644
--- a/crates/ra_analysis/src/completion/mod.rs
+++ b/crates/ra_analysis/src/completion/mod.rs
@@ -9,6 +9,7 @@ use ra_syntax::{
9}; 9};
10use ra_db::SyntaxDatabase; 10use ra_db::SyntaxDatabase;
11use rustc_hash::{FxHashMap}; 11use rustc_hash::{FxHashMap};
12use hir::source_binder;
12 13
13use crate::{ 14use crate::{
14 db, 15 db,
@@ -36,7 +37,7 @@ pub(crate) fn completions(
36 original_file.reparse(&edit) 37 original_file.reparse(&edit)
37 }; 38 };
38 39
39 let module = ctry!(hir::Module::guess_from_position(db, position)?); 40 let module = ctry!(source_binder::module_from_position(db, position)?);
40 41
41 let mut res = Vec::new(); 42 let mut res = Vec::new();
42 let mut has_completions = false; 43 let mut has_completions = false;
@@ -427,7 +428,7 @@ mod tests {
427 // check_snippet_completion(r" 428 // check_snippet_completion(r"
428 // <|> 429 // <|>
429 // ", 430 // ",
430 // r##"[CompletionItem { label: "tfn", lookup: None, snippet: Some("#[test]\nfn $1() {\n $0\n}") }]"##, 431 // r##"[CompletionItem { label: "Test function", lookup: None, snippet: Some("#[test]\nfn test_${1:feature}() {\n$0\n}"##,
431 // ); 432 // );
432 check_snippet_completion(r" 433 check_snippet_completion(r"
433 #[cfg(test)] 434 #[cfg(test)]
@@ -435,7 +436,7 @@ mod tests {
435 <|> 436 <|>
436 } 437 }
437 ", 438 ",
438 r##"[CompletionItem { label: "tfn", lookup: None, snippet: Some("#[test]\nfn $1() {\n $0\n}") }, 439 r##"[CompletionItem { label: "Test function", lookup: Some("tfn"), snippet: Some("#[test]\nfn ${1:feature}() {\n$0\n}") },
439 CompletionItem { label: "pub(crate)", lookup: None, snippet: Some("pub(crate) $0") }]"##, 440 CompletionItem { label: "pub(crate)", lookup: None, snippet: Some("pub(crate) $0") }]"##,
440 ); 441 );
441 } 442 }
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs
index e1a2d5241..f483ed045 100644
--- a/crates/ra_analysis/src/completion/reference_completion.rs
+++ b/crates/ra_analysis/src/completion/reference_completion.rs
@@ -163,7 +163,7 @@ fn complete_path(
163 }; 163 };
164 let target_module = match def_id.resolve(db)? { 164 let target_module = match def_id.resolve(db)? {
165 Def::Module(it) => it, 165 Def::Module(it) => it,
166 Def::Item => return Ok(()), 166 _ => return Ok(()),
167 }; 167 };
168 let module_scope = target_module.scope(db)?; 168 let module_scope = target_module.scope(db)?;
169 let completions = module_scope.entries().map(|(name, _res)| CompletionItem { 169 let completions = module_scope.entries().map(|(name, _res)| CompletionItem {
@@ -177,9 +177,15 @@ fn complete_path(
177 177
178fn complete_mod_item_snippets(acc: &mut Vec<CompletionItem>) { 178fn complete_mod_item_snippets(acc: &mut Vec<CompletionItem>) {
179 acc.push(CompletionItem { 179 acc.push(CompletionItem {
180 label: "tfn".to_string(), 180 label: "Test function".to_string(),
181 lookup: None, 181 lookup: Some("tfn".to_string()),
182 snippet: Some("#[test]\nfn $1() {\n $0\n}".to_string()), 182 snippet: Some(
183 "#[test]\n\
184 fn ${1:feature}() {\n\
185 $0\n\
186 }"
187 .to_string(),
188 ),
183 }); 189 });
184 acc.push(CompletionItem { 190 acc.push(CompletionItem {
185 label: "pub(crate)".to_string(), 191 label: "pub(crate)".to_string(),
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index df2ef293d..b8d774eb5 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -1,7 +1,7 @@
1use std::sync::Arc; 1use std::sync::Arc;
2use salsa::{self, Database}; 2use salsa::{self, Database};
3use ra_db::{LocationIntener, BaseDatabase}; 3use ra_db::{LocationIntener, BaseDatabase};
4use hir::{self, DefId, DefLoc, FnId, SourceItemId}; 4use hir::{self, DefId, DefLoc};
5 5
6use crate::{ 6use crate::{
7 symbol_index, 7 symbol_index,
@@ -15,7 +15,6 @@ pub(crate) struct RootDatabase {
15 15
16#[derive(Debug, Default)] 16#[derive(Debug, Default)]
17struct IdMaps { 17struct IdMaps {
18 fns: LocationIntener<SourceItemId, FnId>,
19 defs: LocationIntener<DefLoc, DefId>, 18 defs: LocationIntener<DefLoc, DefId>,
20} 19}
21 20
@@ -58,12 +57,6 @@ impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase {
58 } 57 }
59} 58}
60 59
61impl AsRef<LocationIntener<hir::SourceItemId, FnId>> for RootDatabase {
62 fn as_ref(&self) -> &LocationIntener<hir::SourceItemId, FnId> {
63 &self.id_maps.fns
64 }
65}
66
67salsa::database_storage! { 60salsa::database_storage! {
68 pub(crate) struct RootDatabaseStorage for RootDatabase { 61 pub(crate) struct RootDatabaseStorage for RootDatabase {
69 impl ra_db::FilesDatabase { 62 impl ra_db::FilesDatabase {
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index f5cb3550e..975afc145 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -16,6 +16,7 @@ use rustc_hash::FxHashSet;
16use salsa::{Database, ParallelDatabase}; 16use salsa::{Database, ParallelDatabase};
17use hir::{ 17use hir::{
18 self, 18 self,
19 source_binder,
19 FnSignatureInfo, 20 FnSignatureInfo,
20 Problem, 21 Problem,
21}; 22};
@@ -166,7 +167,7 @@ impl AnalysisImpl {
166 /// This return `Vec`: a module may be included from several places. We 167 /// This return `Vec`: a module may be included from several places. We
167 /// don't handle this case yet though, so the Vec has length at most one. 168 /// don't handle this case yet though, so the Vec has length at most one.
168 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { 169 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> {
169 let descr = match hir::Module::guess_from_position(&*self.db, position)? { 170 let descr = match source_binder::module_from_position(&*self.db, position)? {
170 None => return Ok(Vec::new()), 171 None => return Ok(Vec::new()),
171 Some(it) => it, 172 Some(it) => it,
172 }; 173 };
@@ -185,15 +186,12 @@ impl AnalysisImpl {
185 } 186 }
186 /// Returns `Vec` for the same reason as `parent_module` 187 /// Returns `Vec` for the same reason as `parent_module`
187 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { 188 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
188 let descr = match hir::Module::guess_from_file_id(&*self.db, file_id)? { 189 let descr = match source_binder::module_from_file_id(&*self.db, file_id)? {
189 None => return Ok(Vec::new()), 190 None => return Ok(Vec::new()),
190 Some(it) => it, 191 Some(it) => it,
191 }; 192 };
192 let root = descr.crate_root(); 193 let root = descr.crate_root();
193 let file_id = root 194 let file_id = root.source().file_id();
194 .source()
195 .as_file()
196 .expect("root module always has a file as a source");
197 195
198 let crate_graph = self.db.crate_graph(); 196 let crate_graph = self.db.crate_graph();
199 let crate_id = crate_graph.crate_id_for_crate_root(file_id); 197 let crate_id = crate_graph.crate_id_for_crate_root(file_id);
@@ -212,12 +210,14 @@ impl AnalysisImpl {
212 let file = self.db.source_file(position.file_id); 210 let file = self.db.source_file(position.file_id);
213 let syntax = file.syntax(); 211 let syntax = file.syntax();
214 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { 212 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
215 if let Some(fn_descr) = 213 if let Some(fn_descr) = source_binder::function_from_child_node(
216 hir::Function::guess_for_name_ref(&*self.db, position.file_id, name_ref) 214 &*self.db,
217 { 215 position.file_id,
216 name_ref.syntax(),
217 )? {
218 let scope = fn_descr.scope(&*self.db); 218 let scope = fn_descr.scope(&*self.db);
219 // First try to resolve the symbol locally 219 // First try to resolve the symbol locally
220 return if let Some(entry) = scope.resolve_local_name(name_ref) { 220 if let Some(entry) = scope.resolve_local_name(name_ref) {
221 let mut vec = vec![]; 221 let mut vec = vec![];
222 vec.push(( 222 vec.push((
223 position.file_id, 223 position.file_id,
@@ -227,18 +227,17 @@ impl AnalysisImpl {
227 kind: NAME, 227 kind: NAME,
228 }, 228 },
229 )); 229 ));
230 Ok(vec) 230 return Ok(vec);
231 } else {
232 // If that fails try the index based approach.
233 self.index_resolve(name_ref)
234 }; 231 };
235 } 232 }
233 // If that fails try the index based approach.
234 return self.index_resolve(name_ref);
236 } 235 }
237 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { 236 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) {
238 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { 237 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
239 if module.has_semi() { 238 if module.has_semi() {
240 let parent_module = 239 let parent_module =
241 hir::Module::guess_from_file_id(&*self.db, position.file_id)?; 240 source_binder::module_from_file_id(&*self.db, position.file_id)?;
242 let child_name = module.name(); 241 let child_name = module.name();
243 match (parent_module, child_name) { 242 match (parent_module, child_name) {
244 (Some(parent_module), Some(child_name)) => { 243 (Some(parent_module), Some(child_name)) => {
@@ -260,11 +259,11 @@ impl AnalysisImpl {
260 Ok(vec![]) 259 Ok(vec![])
261 } 260 }
262 261
263 pub fn find_all_refs(&self, position: FilePosition) -> Vec<(FileId, TextRange)> { 262 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
264 let file = self.db.source_file(position.file_id); 263 let file = self.db.source_file(position.file_id);
265 // Find the binding associated with the offset 264 // Find the binding associated with the offset
266 let (binding, descr) = match find_binding(&self.db, &file, position) { 265 let (binding, descr) = match find_binding(&self.db, &file, position)? {
267 None => return Vec::new(), 266 None => return Ok(Vec::new()),
268 Some(it) => it, 267 Some(it) => it,
269 }; 268 };
270 269
@@ -277,25 +276,36 @@ impl AnalysisImpl {
277 .map(|ref_desc| (position.file_id, ref_desc.range)), 276 .map(|ref_desc| (position.file_id, ref_desc.range)),
278 ); 277 );
279 278
280 return ret; 279 return Ok(ret);
281 280
282 fn find_binding<'a>( 281 fn find_binding<'a>(
283 db: &db::RootDatabase, 282 db: &db::RootDatabase,
284 source_file: &'a SourceFileNode, 283 source_file: &'a SourceFileNode,
285 position: FilePosition, 284 position: FilePosition,
286 ) -> Option<(ast::BindPat<'a>, hir::Function)> { 285 ) -> Cancelable<Option<(ast::BindPat<'a>, hir::Function)>> {
287 let syntax = source_file.syntax(); 286 let syntax = source_file.syntax();
288 if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) { 287 if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) {
289 let descr = hir::Function::guess_for_bind_pat(db, position.file_id, binding)?; 288 let descr = ctry!(source_binder::function_from_child_node(
290 return Some((binding, descr)); 289 db,
290 position.file_id,
291 binding.syntax(),
292 )?);
293 return Ok(Some((binding, descr)));
291 }; 294 };
292 let name_ref = find_node_at_offset::<ast::NameRef>(syntax, position.offset)?; 295 let name_ref = ctry!(find_node_at_offset::<ast::NameRef>(syntax, position.offset));
293 let descr = hir::Function::guess_for_name_ref(db, position.file_id, name_ref)?; 296 let descr = ctry!(source_binder::function_from_child_node(
297 db,
298 position.file_id,
299 name_ref.syntax(),
300 )?);
294 let scope = descr.scope(db); 301 let scope = descr.scope(db);
295 let resolved = scope.resolve_local_name(name_ref)?; 302 let resolved = ctry!(scope.resolve_local_name(name_ref));
296 let resolved = resolved.ptr().resolve(source_file); 303 let resolved = resolved.ptr().resolve(source_file);
297 let binding = find_node_at_offset::<ast::BindPat>(syntax, resolved.range().end())?; 304 let binding = ctry!(find_node_at_offset::<ast::BindPat>(
298 Some((binding, descr)) 305 syntax,
306 resolved.range().end()
307 ));
308 Ok(Some((binding, descr)))
299 } 309 }
300 } 310 }
301 311
@@ -320,7 +330,7 @@ impl AnalysisImpl {
320 fix: None, 330 fix: None,
321 }) 331 })
322 .collect::<Vec<_>>(); 332 .collect::<Vec<_>>();
323 if let Some(m) = hir::Module::guess_from_file_id(&*self.db, file_id)? { 333 if let Some(m) = source_binder::module_from_file_id(&*self.db, file_id)? {
324 for (name_node, problem) in m.problems(&*self.db) { 334 for (name_node, problem) in m.problems(&*self.db) {
325 let diag = match problem { 335 let diag = match problem {
326 Problem::UnresolvedModule { candidate } => { 336 Problem::UnresolvedModule { candidate } => {
@@ -411,7 +421,9 @@ impl AnalysisImpl {
411 if fs.kind == FN_DEF { 421 if fs.kind == FN_DEF {
412 let fn_file = self.db.source_file(fn_file_id); 422 let fn_file = self.db.source_file(fn_file_id);
413 if let Some(fn_def) = find_node_at_offset(fn_file.syntax(), fs.node_range.start()) { 423 if let Some(fn_def) = find_node_at_offset(fn_file.syntax(), fs.node_range.start()) {
414 let descr = hir::Function::guess_from_source(&*self.db, fn_file_id, fn_def); 424 let descr = ctry!(source_binder::function_from_source(
425 &*self.db, fn_file_id, fn_def
426 )?);
415 if let Some(descriptor) = descr.signature_info(&*self.db) { 427 if let Some(descriptor) = descr.signature_info(&*self.db) {
416 // If we have a calling expression let's find which argument we are on 428 // If we have a calling expression let's find which argument we are on
417 let mut current_parameter = None; 429 let mut current_parameter = None;
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index 12df580ba..90528edfd 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -248,7 +248,7 @@ impl Analysis {
248 self.imp.approximately_resolve_symbol(position) 248 self.imp.approximately_resolve_symbol(position)
249 } 249 }
250 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { 250 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
251 Ok(self.imp.find_all_refs(position)) 251 self.imp.find_all_refs(position)
252 } 252 }
253 pub fn doc_comment_for( 253 pub fn doc_comment_for(
254 &self, 254 &self,
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs
index fbe89f444..71d20dbe9 100644
--- a/crates/ra_analysis/tests/tests.rs
+++ b/crates/ra_analysis/tests/tests.rs
@@ -19,6 +19,23 @@ fn get_signature(text: &str) -> (FnSignatureInfo, Option<usize>) {
19} 19}
20 20
21#[test] 21#[test]
22fn approximate_resolve_works_in_items() {
23 let (analysis, pos) = analysis_and_position(
24 "
25 //- /lib.rs
26 struct Foo;
27 enum E { X(Foo<|>) }
28 ",
29 );
30
31 let symbols = analysis.approximately_resolve_symbol(pos).unwrap();
32 assert_eq_dbg(
33 r#"[(FileId(1), FileSymbol { name: "Foo", node_range: [0; 11), kind: STRUCT_DEF })]"#,
34 &symbols,
35 );
36}
37
38#[test]
22fn test_resolve_module() { 39fn test_resolve_module() {
23 let (analysis, pos) = analysis_and_position( 40 let (analysis, pos) = analysis_and_position(
24 " 41 "