aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-10-31 20:41:43 +0000
committerAleksey Kladov <[email protected]>2018-10-31 20:41:43 +0000
commit6be50f7d5de3737464853a589673375fc0cafa97 (patch)
tree2c6da7f3a1234c3f2fd3f330d2c9445953979598 /crates/ra_analysis
parent857c1650efdb51650458f9ec1119adaa49b34371 (diff)
Reformat all
Diffstat (limited to 'crates/ra_analysis')
-rw-r--r--crates/ra_analysis/src/completion.rs57
-rw-r--r--crates/ra_analysis/src/db.rs13
-rw-r--r--crates/ra_analysis/src/descriptors/function/imp.rs12
-rw-r--r--crates/ra_analysis/src/descriptors/function/mod.rs29
-rw-r--r--crates/ra_analysis/src/descriptors/function/scope.rs7
-rw-r--r--crates/ra_analysis/src/descriptors/mod.rs39
-rw-r--r--crates/ra_analysis/src/descriptors/module/imp.rs33
-rw-r--r--crates/ra_analysis/src/descriptors/module/mod.rs30
-rw-r--r--crates/ra_analysis/src/descriptors/module/scope.rs5
-rw-r--r--crates/ra_analysis/src/imp.rs77
-rw-r--r--crates/ra_analysis/src/input.rs9
-rw-r--r--crates/ra_analysis/src/lib.rs47
-rw-r--r--crates/ra_analysis/src/mock_analysis.rs17
-rw-r--r--crates/ra_analysis/src/symbol_index.rs5
-rw-r--r--crates/ra_analysis/src/syntax_ptr.rs23
-rw-r--r--crates/ra_analysis/tests/tests.rs105
16 files changed, 278 insertions, 230 deletions
diff --git a/crates/ra_analysis/src/completion.rs b/crates/ra_analysis/src/completion.rs
index 286b6c376..6bd1233f9 100644
--- a/crates/ra_analysis/src/completion.rs
+++ b/crates/ra_analysis/src/completion.rs
@@ -1,22 +1,22 @@
1use rustc_hash::{FxHashMap, FxHashSet}; 1use ra_editor::find_node_at_offset;
2use ra_editor::{find_node_at_offset};
3use ra_syntax::{ 2use ra_syntax::{
4 AtomEdit, File, TextUnit, AstNode, SyntaxNodeRef,
5 algo::visit::{visitor, visitor_ctx, Visitor, VisitorCtx}, 3 algo::visit::{visitor, visitor_ctx, Visitor, VisitorCtx},
6 ast::{self, AstChildren, LoopBodyOwner, ModuleItemOwner}, 4 ast::{self, AstChildren, LoopBodyOwner, ModuleItemOwner},
5 AstNode, AtomEdit, File,
7 SyntaxKind::*, 6 SyntaxKind::*,
7 SyntaxNodeRef, TextUnit,
8}; 8};
9use rustc_hash::{FxHashMap, FxHashSet};
9 10
10use crate::{ 11use crate::{
11 FileId, Cancelable,
12 input::FilesDatabase,
13 db::{self, SyntaxDatabase}, 12 db::{self, SyntaxDatabase},
14 descriptors::DescriptorDatabase,
15 descriptors::function::FnScopes, 13 descriptors::function::FnScopes,
16 descriptors::module::{ModuleTree, ModuleId, ModuleScope}, 14 descriptors::module::{ModuleId, ModuleScope, ModuleTree},
15 descriptors::DescriptorDatabase,
16 input::FilesDatabase,
17 Cancelable, FileId,
17}; 18};
18 19
19
20#[derive(Debug)] 20#[derive(Debug)]
21pub struct CompletionItem { 21pub struct CompletionItem {
22 /// What user sees in pop-up 22 /// What user sees in pop-up
@@ -27,7 +27,11 @@ pub struct CompletionItem {
27 pub snippet: Option<String>, 27 pub snippet: Option<String>,
28} 28}
29 29
30pub(crate) fn resolve_based_completion(db: &db::RootDatabase, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> { 30pub(crate) fn resolve_based_completion(
31 db: &db::RootDatabase,
32 file_id: FileId,
33 offset: TextUnit,
34) -> Cancelable<Option<Vec<CompletionItem>>> {
31 let source_root_id = db.file_source_root(file_id); 35 let source_root_id = db.file_source_root(file_id);
32 let file = db.file_syntax(file_id); 36 let file = db.file_syntax(file_id);
33 let module_tree = db.module_tree(source_root_id)?; 37 let module_tree = db.module_tree(source_root_id)?;
@@ -56,9 +60,12 @@ pub(crate) fn resolve_based_completion(db: &db::RootDatabase, file_id: FileId, o
56 Ok(Some(res)) 60 Ok(Some(res))
57} 61}
58 62
59 63pub(crate) fn find_target_module(
60 64 module_tree: &ModuleTree,
61pub(crate) fn find_target_module(module_tree: &ModuleTree, module_id: ModuleId, file: &File, offset: TextUnit) -> Option<ModuleId> { 65 module_id: ModuleId,
66 file: &File,
67 offset: TextUnit,
68) -> Option<ModuleId> {
62 let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), offset)?; 69 let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), offset)?;
63 let mut crate_path = crate_path(name_ref)?; 70 let mut crate_path = crate_path(name_ref)?;
64 71
@@ -71,8 +78,10 @@ pub(crate) fn find_target_module(module_tree: &ModuleTree, module_id: ModuleId,
71} 78}
72 79
73fn crate_path(name_ref: ast::NameRef) -> Option<Vec<ast::NameRef>> { 80fn crate_path(name_ref: ast::NameRef) -> Option<Vec<ast::NameRef>> {
74 let mut path = name_ref.syntax() 81 let mut path = name_ref
75 .parent().and_then(ast::PathSegment::cast)? 82 .syntax()
83 .parent()
84 .and_then(ast::PathSegment::cast)?
76 .parent_path(); 85 .parent_path();
77 let mut res = Vec::new(); 86 let mut res = Vec::new();
78 loop { 87 loop {
@@ -80,8 +89,7 @@ fn crate_path(name_ref: ast::NameRef) -> Option<Vec<ast::NameRef>> {
80 match segment.kind()? { 89 match segment.kind()? {
81 ast::PathSegmentKind::Name(name) => res.push(name), 90 ast::PathSegmentKind::Name(name) => res.push(name),
82 ast::PathSegmentKind::CrateKw => break, 91 ast::PathSegmentKind::CrateKw => break,
83 ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw => 92 ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw => return None,
84 return None,
85 } 93 }
86 path = path.qualifier()?; 94 path = path.qualifier()?;
87 } 95 }
@@ -89,7 +97,6 @@ fn crate_path(name_ref: ast::NameRef) -> Option<Vec<ast::NameRef>> {
89 Some(res) 97 Some(res)
90} 98}
91 99
92
93pub(crate) fn scope_completion( 100pub(crate) fn scope_completion(
94 db: &db::RootDatabase, 101 db: &db::RootDatabase,
95 file_id: FileId, 102 file_id: FileId,
@@ -158,11 +165,7 @@ fn complete_module_items(
158 ); 165 );
159} 166}
160 167
161fn complete_name_ref( 168fn complete_name_ref(file: &File, name_ref: ast::NameRef, acc: &mut Vec<CompletionItem>) {
162 file: &File,
163 name_ref: ast::NameRef,
164 acc: &mut Vec<CompletionItem>,
165) {
166 if !is_node::<ast::Path>(name_ref.syntax()) { 169 if !is_node::<ast::Path>(name_ref.syntax()) {
167 return; 170 return;
168 } 171 }
@@ -273,7 +276,11 @@ fn is_in_loop_body(name_ref: ast::NameRef) -> bool {
273 .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body) 276 .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body)
274 .accept(node); 277 .accept(node);
275 if let Some(Some(body)) = loop_body { 278 if let Some(Some(body)) = loop_body {
276 if name_ref.syntax().range().is_subrange(&body.syntax().range()) { 279 if name_ref
280 .syntax()
281 .range()
282 .is_subrange(&body.syntax().range())
283 {
277 return true; 284 return true;
278 } 285 }
279 } 286 }
@@ -368,9 +375,9 @@ fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<Completi
368 375
369#[cfg(test)] 376#[cfg(test)]
370mod tests { 377mod tests {
371 use test_utils::{assert_eq_dbg}; 378 use test_utils::assert_eq_dbg;
372 379
373 use crate::mock_analysis::{single_file_with_position}; 380 use crate::mock_analysis::single_file_with_position;
374 381
375 use super::*; 382 use super::*;
376 383
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index f1ace3d5a..9ab273ad7 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -1,6 +1,4 @@
1use std::{ 1use std::sync::Arc;
2 sync::Arc,
3};
4 2
5use ra_editor::LineIndex; 3use ra_editor::LineIndex;
6use ra_syntax::File; 4use ra_syntax::File;
@@ -8,14 +6,13 @@ use salsa;
8 6
9use crate::{ 7use crate::{
10 db, 8 db,
11 Cancelable, Canceled,
12 descriptors::{ 9 descriptors::{
13 DescriptorDatabase, SubmodulesQuery, ModuleTreeQuery, ModuleScopeQuery, 10 DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleScopeQuery, ModuleTreeQuery,
14 FnSyntaxQuery, FnScopesQuery 11 SubmodulesQuery,
15 }, 12 },
16 symbol_index::SymbolIndex, 13 symbol_index::SymbolIndex,
17 syntax_ptr::{SyntaxPtrDatabase, ResolveSyntaxPtrQuery}, 14 syntax_ptr::{ResolveSyntaxPtrQuery, SyntaxPtrDatabase},
18 FileId, 15 Cancelable, Canceled, FileId,
19}; 16};
20 17
21#[derive(Default, Debug)] 18#[derive(Default, Debug)]
diff --git a/crates/ra_analysis/src/descriptors/function/imp.rs b/crates/ra_analysis/src/descriptors/function/imp.rs
index 0a006f733..11fffeefc 100644
--- a/crates/ra_analysis/src/descriptors/function/imp.rs
+++ b/crates/ra_analysis/src/descriptors/function/imp.rs
@@ -1,14 +1,10 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{ 3use ra_syntax::ast::{AstNode, FnDef, FnDefNode};
4 ast::{AstNode, FnDef, FnDefNode},
5};
6 4
7use crate::{ 5use crate::descriptors::{
8 descriptors::{ 6 function::{FnId, FnScopes},
9 DescriptorDatabase, 7 DescriptorDatabase,
10 function::{FnId, FnScopes},
11 },
12}; 8};
13 9
14/// Resolve `FnId` to the corresponding `SyntaxNode` 10/// Resolve `FnId` to the corresponding `SyntaxNode`
diff --git a/crates/ra_analysis/src/descriptors/function/mod.rs b/crates/ra_analysis/src/descriptors/function/mod.rs
index ae40f3e8f..d5db28a64 100644
--- a/crates/ra_analysis/src/descriptors/function/mod.rs
+++ b/crates/ra_analysis/src/descriptors/function/mod.rs
@@ -1,20 +1,16 @@
1pub(super) mod imp; 1pub(super) mod imp;
2mod scope; 2mod scope;
3 3
4use std::cmp::{min, max}; 4use std::cmp::{max, min};
5 5
6use ra_syntax::{ 6use ra_syntax::{
7 ast::{self, AstNode, DocCommentsOwner, NameOwner}, 7 ast::{self, AstNode, DocCommentsOwner, NameOwner},
8 TextRange, TextUnit 8 TextRange, TextUnit,
9}; 9};
10 10
11use crate::{ 11use crate::{syntax_ptr::SyntaxPtr, FileId};
12 FileId,
13 syntax_ptr::SyntaxPtr
14};
15
16pub(crate) use self::scope::{FnScopes, resolve_local_name};
17 12
13pub(crate) use self::scope::{resolve_local_name, FnScopes};
18 14
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20pub(crate) struct FnId(SyntaxPtr); 16pub(crate) struct FnId(SyntaxPtr);
@@ -26,14 +22,13 @@ impl FnId {
26 } 22 }
27} 23}
28 24
29
30#[derive(Debug, Clone)] 25#[derive(Debug, Clone)]
31pub struct FnDescriptor { 26pub struct FnDescriptor {
32 pub name: String, 27 pub name: String,
33 pub label: String, 28 pub label: String,
34 pub ret_type: Option<String>, 29 pub ret_type: Option<String>,
35 pub params: Vec<String>, 30 pub params: Vec<String>,
36 pub doc: Option<String> 31 pub doc: Option<String>,
37} 32}
38 33
39impl FnDescriptor { 34impl FnDescriptor {
@@ -57,7 +52,9 @@ impl FnDescriptor {
57 }; 52 };
58 53
59 if let Some((comment_range, docs)) = FnDescriptor::extract_doc_comments(node) { 54 if let Some((comment_range, docs)) = FnDescriptor::extract_doc_comments(node) {
60 let comment_range = comment_range.checked_sub(node.syntax().range().start()).unwrap(); 55 let comment_range = comment_range
56 .checked_sub(node.syntax().range().start())
57 .unwrap();
61 let start = comment_range.start().to_usize(); 58 let start = comment_range.start().to_usize();
62 let end = comment_range.end().to_usize(); 59 let end = comment_range.end().to_usize();
63 60
@@ -94,7 +91,7 @@ impl FnDescriptor {
94 ret_type, 91 ret_type,
95 params, 92 params,
96 label: label.trim().to_owned(), 93 label: label.trim().to_owned(),
97 doc 94 doc,
98 }) 95 })
99 } 96 }
100 97
@@ -105,10 +102,13 @@ impl FnDescriptor {
105 102
106 let comment_text = node.doc_comment_text(); 103 let comment_text = node.doc_comment_text();
107 104
108 let (begin, end) = node.doc_comments() 105 let (begin, end) = node
106 .doc_comments()
109 .map(|comment| comment.syntax().range()) 107 .map(|comment| comment.syntax().range())
110 .map(|range| (range.start().to_usize(), range.end().to_usize())) 108 .map(|range| (range.start().to_usize(), range.end().to_usize()))
111 .fold((std::usize::MAX, std::usize::MIN), |acc, range| (min(acc.0, range.0), max(acc.1, range.1))); 109 .fold((std::usize::MAX, std::usize::MIN), |acc, range| {
110 (min(acc.0, range.0), max(acc.1, range.1))
111 });
112 112
113 let range = TextRange::from_to(TextUnit::from_usize(begin), TextUnit::from_usize(end)); 113 let range = TextRange::from_to(TextUnit::from_usize(begin), TextUnit::from_usize(end));
114 114
@@ -134,4 +134,3 @@ impl FnDescriptor {
134 res 134 res
135 } 135 }
136} 136}
137
diff --git a/crates/ra_analysis/src/descriptors/function/scope.rs b/crates/ra_analysis/src/descriptors/function/scope.rs
index d9929414c..62b46ffba 100644
--- a/crates/ra_analysis/src/descriptors/function/scope.rs
+++ b/crates/ra_analysis/src/descriptors/function/scope.rs
@@ -51,9 +51,7 @@ impl FnScopes {
51 &self.get(scope).entries 51 &self.get(scope).entries
52 } 52 }
53 pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator<Item = ScopeId> + 'a { 53 pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator<Item = ScopeId> + 'a {
54 generate(self.scope_for(node), move |&scope| { 54 generate(self.scope_for(node), move |&scope| self.get(scope).parent)
55 self.get(scope).parent
56 })
57 } 55 }
58 fn root_scope(&mut self) -> ScopeId { 56 fn root_scope(&mut self) -> ScopeId {
59 let res = ScopeId(self.scopes.len() as u32); 57 let res = ScopeId(self.scopes.len() as u32);
@@ -273,13 +271,12 @@ pub fn resolve_local_name<'a>(
273 271
274#[cfg(test)] 272#[cfg(test)]
275mod tests { 273mod tests {
274 use ra_editor::find_node_at_offset;
276 use ra_syntax::File; 275 use ra_syntax::File;
277 use test_utils::extract_offset; 276 use test_utils::extract_offset;
278 use ra_editor::{find_node_at_offset};
279 277
280 use super::*; 278 use super::*;
281 279
282
283 fn do_check(code: &str, expected: &[&str]) { 280 fn do_check(code: &str, expected: &[&str]) {
284 let (off, code) = extract_offset(code); 281 let (off, code) = extract_offset(code);
285 let code = { 282 let code = {
diff --git a/crates/ra_analysis/src/descriptors/mod.rs b/crates/ra_analysis/src/descriptors/mod.rs
index e27f8314a..c28764336 100644
--- a/crates/ra_analysis/src/descriptors/mod.rs
+++ b/crates/ra_analysis/src/descriptors/mod.rs
@@ -1,24 +1,22 @@
1pub(crate) mod module;
2pub(crate) mod function; 1pub(crate) mod function;
2pub(crate) mod module;
3 3
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use ra_syntax::{ 6use ra_syntax::{
7 SmolStr,
8 ast::{self, AstNode, FnDefNode}, 7 ast::{self, AstNode, FnDefNode},
9 TextRange 8 SmolStr, TextRange,
10}; 9};
11 10
12use crate::{ 11use crate::{
13 FileId, Cancelable,
14 db::SyntaxDatabase, 12 db::SyntaxDatabase,
15 descriptors::module::{ModuleTree, ModuleId, ModuleScope}, 13 descriptors::function::{resolve_local_name, FnId, FnScopes},
16 descriptors::function::{FnId, FnScopes, resolve_local_name}, 14 descriptors::module::{ModuleId, ModuleScope, ModuleTree},
17 input::SourceRootId, 15 input::SourceRootId,
18 syntax_ptr::{SyntaxPtrDatabase, LocalSyntaxPtr}, 16 syntax_ptr::{LocalSyntaxPtr, SyntaxPtrDatabase},
17 Cancelable, FileId,
19}; 18};
20 19
21
22salsa::query_group! { 20salsa::query_group! {
23 pub(crate) trait DescriptorDatabase: SyntaxDatabase + SyntaxPtrDatabase { 21 pub(crate) trait DescriptorDatabase: SyntaxDatabase + SyntaxPtrDatabase {
24 fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> { 22 fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> {
@@ -49,23 +47,20 @@ salsa::query_group! {
49#[derive(Debug)] 47#[derive(Debug)]
50pub struct ReferenceDescriptor { 48pub struct ReferenceDescriptor {
51 pub range: TextRange, 49 pub range: TextRange,
52 pub name: String 50 pub name: String,
53} 51}
54 52
55#[derive(Debug)] 53#[derive(Debug)]
56pub struct DeclarationDescriptor<'a> { 54pub struct DeclarationDescriptor<'a> {
57 pat: ast::BindPat<'a>, 55 pat: ast::BindPat<'a>,
58 pub range: TextRange 56 pub range: TextRange,
59} 57}
60 58
61impl<'a> DeclarationDescriptor<'a> { 59impl<'a> DeclarationDescriptor<'a> {
62 pub fn new(pat: ast::BindPat) -> DeclarationDescriptor { 60 pub fn new(pat: ast::BindPat) -> DeclarationDescriptor {
63 let range = pat.syntax().range(); 61 let range = pat.syntax().range();
64 62
65 DeclarationDescriptor { 63 DeclarationDescriptor { pat, range }
66 pat,
67 range
68 }
69 } 64 }
70 65
71 pub fn find_all_refs(&self) -> Vec<ReferenceDescriptor> { 66 pub fn find_all_refs(&self) -> Vec<ReferenceDescriptor> {
@@ -73,22 +68,22 @@ impl<'a> DeclarationDescriptor<'a> {
73 68
74 let fn_def = match self.pat.syntax().ancestors().find_map(ast::FnDef::cast) { 69 let fn_def = match self.pat.syntax().ancestors().find_map(ast::FnDef::cast) {
75 Some(def) => def, 70 Some(def) => def,
76 None => return Default::default() 71 None => return Default::default(),
77 }; 72 };
78 73
79 let fn_scopes = FnScopes::new(fn_def); 74 let fn_scopes = FnScopes::new(fn_def);
80 75
81 let refs : Vec<_> = fn_def.syntax().descendants() 76 let refs: Vec<_> = fn_def
77 .syntax()
78 .descendants()
82 .filter_map(ast::NameRef::cast) 79 .filter_map(ast::NameRef::cast)
83 .filter(|name_ref| { 80 .filter(|name_ref| match resolve_local_name(*name_ref, &fn_scopes) {
84 match resolve_local_name(*name_ref, &fn_scopes) { 81 None => false,
85 None => false, 82 Some(entry) => entry.ptr() == name_ptr,
86 Some(entry) => entry.ptr() == name_ptr,
87 }
88 }) 83 })
89 .map(|name_ref| ReferenceDescriptor { 84 .map(|name_ref| ReferenceDescriptor {
90 name: name_ref.syntax().text().to_string(), 85 name: name_ref.syntax().text().to_string(),
91 range : name_ref.syntax().range(), 86 range: name_ref.syntax().range(),
92 }) 87 })
93 .collect(); 88 .collect();
94 89
diff --git a/crates/ra_analysis/src/descriptors/module/imp.rs b/crates/ra_analysis/src/descriptors/module/imp.rs
index dae3a356d..1c102f4e5 100644
--- a/crates/ra_analysis/src/descriptors/module/imp.rs
+++ b/crates/ra_analysis/src/descriptors/module/imp.rs
@@ -1,24 +1,25 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use relative_path::RelativePathBuf;
4use rustc_hash::{FxHashMap, FxHashSet};
5use ra_syntax::{ 3use ra_syntax::{
6 SmolStr,
7 ast::{self, NameOwner}, 4 ast::{self, NameOwner},
5 SmolStr,
8}; 6};
7use relative_path::RelativePathBuf;
8use rustc_hash::{FxHashMap, FxHashSet};
9 9
10use crate::{ 10use crate::{
11 FileId, Cancelable, FileResolverImp, db, 11 db,
12 input::{SourceRoot, SourceRootId},
13 descriptors::DescriptorDatabase, 12 descriptors::DescriptorDatabase,
13 input::{SourceRoot, SourceRootId},
14 Cancelable, FileId, FileResolverImp,
14}; 15};
15 16
16use super::{ 17use super::{LinkData, LinkId, ModuleData, ModuleId, ModuleScope, ModuleTree, Problem};
17 ModuleData, ModuleTree, ModuleId, LinkId, LinkData, Problem, ModuleScope
18};
19
20 18
21pub(crate) fn submodules(db: &impl DescriptorDatabase, file_id: FileId) -> Cancelable<Arc<Vec<SmolStr>>> { 19pub(crate) fn submodules(
20 db: &impl DescriptorDatabase,
21 file_id: FileId,
22) -> Cancelable<Arc<Vec<SmolStr>>> {
22 db::check_canceled(db)?; 23 db::check_canceled(db)?;
23 let file = db.file_syntax(file_id); 24 let file = db.file_syntax(file_id);
24 let root = file.ast(); 25 let root = file.ast();
@@ -57,13 +58,11 @@ pub(crate) fn module_tree(
57 Ok(Arc::new(res)) 58 Ok(Arc::new(res))
58} 59}
59 60
60
61#[derive(Clone, Hash, PartialEq, Eq, Debug)] 61#[derive(Clone, Hash, PartialEq, Eq, Debug)]
62pub struct Submodule { 62pub struct Submodule {
63 pub name: SmolStr, 63 pub name: SmolStr,
64} 64}
65 65
66
67fn create_module_tree<'a>( 66fn create_module_tree<'a>(
68 db: &impl DescriptorDatabase, 67 db: &impl DescriptorDatabase,
69 source_root: SourceRootId, 68 source_root: SourceRootId,
@@ -82,7 +81,15 @@ fn create_module_tree<'a>(
82 continue; // TODO: use explicit crate_roots here 81 continue; // TODO: use explicit crate_roots here
83 } 82 }
84 assert!(!roots.contains_key(&file_id)); 83 assert!(!roots.contains_key(&file_id));
85 let module_id = build_subtree(db, &source_root, &mut tree, &mut visited, &mut roots, None, file_id)?; 84 let module_id = build_subtree(
85 db,
86 &source_root,
87 &mut tree,
88 &mut visited,
89 &mut roots,
90 None,
91 file_id,
92 )?;
86 roots.insert(file_id, module_id); 93 roots.insert(file_id, module_id);
87 } 94 }
88 Ok(tree) 95 Ok(tree)
diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs
index 667553f74..302e3e81c 100644
--- a/crates/ra_analysis/src/descriptors/module/mod.rs
+++ b/crates/ra_analysis/src/descriptors/module/mod.rs
@@ -1,8 +1,11 @@
1pub(super) mod imp; 1pub(super) mod imp;
2pub(crate) mod scope; 2pub(crate) mod scope;
3 3
4use ra_syntax::{
5 ast::{self, AstNode, NameOwner},
6 SmolStr, SyntaxNode,
7};
4use relative_path::RelativePathBuf; 8use relative_path::RelativePathBuf;
5use ra_syntax::{ast::{self, NameOwner, AstNode}, SmolStr, SyntaxNode};
6 9
7use crate::FileId; 10use crate::FileId;
8 11
@@ -16,9 +19,11 @@ pub(crate) struct ModuleTree {
16 19
17impl ModuleTree { 20impl ModuleTree {
18 pub(crate) fn modules_for_file(&self, file_id: FileId) -> Vec<ModuleId> { 21 pub(crate) fn modules_for_file(&self, file_id: FileId) -> Vec<ModuleId> {
19 self.mods.iter() 22 self.mods
23 .iter()
20 .enumerate() 24 .enumerate()
21 .filter(|(_idx, it)| it.file_id == file_id).map(|(idx, _)| ModuleId(idx as u32)) 25 .filter(|(_idx, it)| it.file_id == file_id)
26 .map(|(idx, _)| ModuleId(idx as u32))
22 .collect() 27 .collect()
23 } 28 }
24 29
@@ -50,7 +55,7 @@ impl ModuleId {
50 } 55 }
51 pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { 56 pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> {
52 tree.module(self).parent 57 tree.module(self).parent
53 } 58 }
54 pub(crate) fn parent(self, tree: &ModuleTree) -> Option<ModuleId> { 59 pub(crate) fn parent(self, tree: &ModuleTree) -> Option<ModuleId> {
55 let link = self.parent_link(tree)?; 60 let link = self.parent_link(tree)?;
56 Some(tree.link(link).owner) 61 Some(tree.link(link).owner)
@@ -69,18 +74,15 @@ impl ModuleId {
69 curr 74 curr
70 } 75 }
71 pub(crate) fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> { 76 pub(crate) fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> {
72 let link = tree.module(self) 77 let link = tree
78 .module(self)
73 .children 79 .children
74 .iter() 80 .iter()
75 .map(|&it| tree.link(it)) 81 .map(|&it| tree.link(it))
76 .find(|it| it.name == name)?; 82 .find(|it| it.name == name)?;
77 Some(*link.points_to.first()?) 83 Some(*link.points_to.first()?)
78 } 84 }
79 pub(crate) fn problems( 85 pub(crate) fn problems(self, tree: &ModuleTree, root: ast::Root) -> Vec<(SyntaxNode, Problem)> {
80 self,
81 tree: &ModuleTree,
82 root: ast::Root,
83 ) -> Vec<(SyntaxNode, Problem)> {
84 tree.module(self) 86 tree.module(self)
85 .children 87 .children
86 .iter() 88 .iter()
@@ -98,11 +100,7 @@ impl LinkId {
98 pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId { 100 pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId {
99 tree.link(self).owner 101 tree.link(self).owner
100 } 102 }
101 pub(crate) fn bind_source<'a>( 103 pub(crate) fn bind_source<'a>(self, tree: &ModuleTree, root: ast::Root<'a>) -> ast::Module<'a> {
102 self,
103 tree: &ModuleTree,
104 root: ast::Root<'a>,
105 ) -> ast::Module<'a> {
106 imp::modules(root) 104 imp::modules(root)
107 .find(|(name, _)| name == &tree.link(self).name) 105 .find(|(name, _)| name == &tree.link(self).name)
108 .unwrap() 106 .unwrap()
@@ -125,7 +123,6 @@ struct LinkData {
125 problem: Option<Problem>, 123 problem: Option<Problem>,
126} 124}
127 125
128
129impl ModuleTree { 126impl ModuleTree {
130 fn module(&self, id: ModuleId) -> &ModuleData { 127 fn module(&self, id: ModuleId) -> &ModuleData {
131 &self.mods[id.0 as usize] 128 &self.mods[id.0 as usize]
@@ -152,4 +149,3 @@ impl ModuleTree {
152 id 149 id
153 } 150 }
154} 151}
155
diff --git a/crates/ra_analysis/src/descriptors/module/scope.rs b/crates/ra_analysis/src/descriptors/module/scope.rs
index 846b8b44f..681e272c2 100644
--- a/crates/ra_analysis/src/descriptors/module/scope.rs
+++ b/crates/ra_analysis/src/descriptors/module/scope.rs
@@ -1,9 +1,8 @@
1//! Backend for module-level scope resolution & completion 1//! Backend for module-level scope resolution & completion
2 2
3
4use ra_syntax::{ 3use ra_syntax::{
5 ast::{self, ModuleItemOwner}, 4 ast::{self, ModuleItemOwner},
6 File, AstNode, SmolStr, 5 AstNode, File, SmolStr,
7}; 6};
8 7
9use crate::syntax_ptr::LocalSyntaxPtr; 8use crate::syntax_ptr::LocalSyntaxPtr;
@@ -103,7 +102,7 @@ fn collect_imports(tree: ast::UseTree, acc: &mut Vec<Entry>) {
103#[cfg(test)] 102#[cfg(test)]
104mod tests { 103mod tests {
105 use super::*; 104 use super::*;
106 use ra_syntax::{File}; 105 use ra_syntax::File;
107 106
108 fn do_check(code: &str, expected: &[&str]) { 107 fn do_check(code: &str, expected: &[&str]) {
109 let file = File::parse(&code); 108 let file = File::parse(&code);
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index 1eb8cb912..44077b507 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -13,24 +13,21 @@ use ra_syntax::{
13use rayon::prelude::*; 13use rayon::prelude::*;
14use relative_path::RelativePath; 14use relative_path::RelativePath;
15use rustc_hash::FxHashSet; 15use rustc_hash::FxHashSet;
16use salsa::{ParallelDatabase, Database}; 16use salsa::{Database, ParallelDatabase};
17 17
18use crate::{ 18use crate::{
19 AnalysisChange, 19 completion::{resolve_based_completion, scope_completion, CompletionItem},
20 db::{ 20 db::{self, FileSyntaxQuery, SyntaxDatabase},
21 self, SyntaxDatabase, FileSyntaxQuery,
22 },
23 input::{SourceRootId, FilesDatabase, SourceRoot, WORKSPACE},
24 descriptors::{ 21 descriptors::{
25 DescriptorDatabase, DeclarationDescriptor,
26 module::{ModuleTree, Problem},
27 function::{FnDescriptor, FnId}, 22 function::{FnDescriptor, FnId},
23 module::{ModuleTree, Problem},
24 DeclarationDescriptor, DescriptorDatabase,
28 }, 25 },
29 completion::{scope_completion, resolve_based_completion, CompletionItem}, 26 input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE},
30 symbol_index::SymbolIndex, 27 symbol_index::SymbolIndex,
31 syntax_ptr::SyntaxPtrDatabase, 28 syntax_ptr::SyntaxPtrDatabase,
32 CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, Position, 29 AnalysisChange, Cancelable, CrateGraph, CrateId, Diagnostic, FileId, FileResolver,
33 Query, SourceChange, SourceFileEdit, Cancelable, 30 FileSystemEdit, Position, Query, SourceChange, SourceFileEdit,
34}; 31};
35 32
36#[derive(Clone, Debug)] 33#[derive(Clone, Debug)]
@@ -94,7 +91,6 @@ pub(crate) struct AnalysisHostImpl {
94 db: db::RootDatabase, 91 db: db::RootDatabase,
95} 92}
96 93
97
98impl AnalysisHostImpl { 94impl AnalysisHostImpl {
99 pub fn new() -> AnalysisHostImpl { 95 pub fn new() -> AnalysisHostImpl {
100 let db = db::RootDatabase::default(); 96 let db = db::RootDatabase::default();
@@ -108,7 +104,7 @@ impl AnalysisHostImpl {
108 } 104 }
109 pub fn analysis(&self) -> AnalysisImpl { 105 pub fn analysis(&self) -> AnalysisImpl {
110 AnalysisImpl { 106 AnalysisImpl {
111 db: self.db.fork() // freeze revision here 107 db: self.db.fork(), // freeze revision here
112 } 108 }
113 } 109 }
114 pub fn apply_change(&mut self, change: AnalysisChange) { 110 pub fn apply_change(&mut self, change: AnalysisChange) {
@@ -120,7 +116,8 @@ impl AnalysisHostImpl {
120 .set(file_id, Arc::new(text)) 116 .set(file_id, Arc::new(text))
121 } 117 }
122 if !(change.files_added.is_empty() && change.files_removed.is_empty()) { 118 if !(change.files_added.is_empty() && change.files_removed.is_empty()) {
123 let file_resolver = change.file_resolver 119 let file_resolver = change
120 .file_resolver
124 .expect("change resolver when changing set of files"); 121 .expect("change resolver when changing set of files");
125 let mut source_root = SourceRoot::clone(&self.db.source_root(WORKSPACE)); 122 let mut source_root = SourceRoot::clone(&self.db.source_root(WORKSPACE));
126 for (file_id, text) in change.files_added { 123 for (file_id, text) in change.files_added {
@@ -174,7 +171,8 @@ impl AnalysisHostImpl {
174 .set((), Arc::new(libraries)); 171 .set((), Arc::new(libraries));
175 } 172 }
176 if let Some(crate_graph) = change.crate_graph { 173 if let Some(crate_graph) = change.crate_graph {
177 self.db.query(crate::input::CrateGraphQuery) 174 self.db
175 .query(crate::input::CrateGraphQuery)
178 .set((), Arc::new(crate_graph)) 176 .set((), Arc::new(crate_graph))
179 } 177 }
180 } 178 }
@@ -194,18 +192,22 @@ impl AnalysisImpl {
194 } 192 }
195 pub fn world_symbols(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> { 193 pub fn world_symbols(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> {
196 let buf: Vec<Arc<SymbolIndex>> = if query.libs { 194 let buf: Vec<Arc<SymbolIndex>> = if query.libs {
197 self.db.libraries().iter() 195 self.db
196 .libraries()
197 .iter()
198 .map(|&lib_id| self.db.library_symbols(lib_id)) 198 .map(|&lib_id| self.db.library_symbols(lib_id))
199 .collect() 199 .collect()
200 } else { 200 } else {
201 let files = &self.db.source_root(WORKSPACE).files; 201 let files = &self.db.source_root(WORKSPACE).files;
202 let db = self.db.clone(); 202 let db = self.db.clone();
203 files.par_iter() 203 files
204 .par_iter()
204 .map_with(db, |db, &file_id| db.file_symbols(file_id)) 205 .map_with(db, |db, &file_id| db.file_symbols(file_id))
205 .filter_map(|it| it.ok()) 206 .filter_map(|it| it.ok())
206 .collect() 207 .collect()
207 }; 208 };
208 self.db.query(FileSyntaxQuery) 209 self.db
210 .query(FileSyntaxQuery)
209 .sweep(salsa::SweepStrategy::default().discard_values()); 211 .sweep(salsa::SweepStrategy::default().discard_values());
210 Ok(query.search(&buf)) 212 Ok(query.search(&buf))
211 } 213 }
@@ -216,7 +218,8 @@ impl AnalysisImpl {
216 pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { 218 pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> {
217 let module_tree = self.module_tree(file_id)?; 219 let module_tree = self.module_tree(file_id)?;
218 220
219 let res = module_tree.modules_for_file(file_id) 221 let res = module_tree
222 .modules_for_file(file_id)
220 .into_iter() 223 .into_iter()
221 .filter_map(|module_id| { 224 .filter_map(|module_id| {
222 let link = module_id.parent_link(&module_tree)?; 225 let link = module_id.parent_link(&module_tree)?;
@@ -237,7 +240,8 @@ impl AnalysisImpl {
237 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { 240 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
238 let module_tree = self.module_tree(file_id)?; 241 let module_tree = self.module_tree(file_id)?;
239 let crate_graph = self.db.crate_graph(); 242 let crate_graph = self.db.crate_graph();
240 let res = module_tree.modules_for_file(file_id) 243 let res = module_tree
244 .modules_for_file(file_id)
241 .into_iter() 245 .into_iter()
242 .map(|it| it.root(&module_tree)) 246 .map(|it| it.root(&module_tree))
243 .map(|it| it.file_id(&module_tree)) 247 .map(|it| it.file_id(&module_tree))
@@ -249,7 +253,11 @@ impl AnalysisImpl {
249 pub fn crate_root(&self, crate_id: CrateId) -> FileId { 253 pub fn crate_root(&self, crate_id: CrateId) -> FileId {
250 self.db.crate_graph().crate_roots[&crate_id] 254 self.db.crate_graph().crate_roots[&crate_id]
251 } 255 }
252 pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> { 256 pub fn completions(
257 &self,
258 file_id: FileId,
259 offset: TextUnit,
260 ) -> Cancelable<Option<Vec<CompletionItem>>> {
253 let mut res = Vec::new(); 261 let mut res = Vec::new();
254 let mut has_completions = false; 262 let mut has_completions = false;
255 if let Some(scope_based) = scope_completion(&self.db, file_id, offset) { 263 if let Some(scope_based) = scope_completion(&self.db, file_id, offset) {
@@ -260,11 +268,7 @@ impl AnalysisImpl {
260 res.extend(scope_based); 268 res.extend(scope_based);
261 has_completions = true; 269 has_completions = true;
262 } 270 }
263 let res = if has_completions { 271 let res = if has_completions { Some(res) } else { None };
264 Some(res)
265 } else {
266 None
267 };
268 Ok(res) 272 Ok(res)
269 } 273 }
270 pub fn approximately_resolve_symbol( 274 pub fn approximately_resolve_symbol(
@@ -326,12 +330,11 @@ impl AnalysisImpl {
326 let syntax = file.syntax(); 330 let syntax = file.syntax();
327 331
328 // Find the binding associated with the offset 332 // Find the binding associated with the offset
329 let maybe_binding = find_node_at_offset::<ast::BindPat>(syntax, offset) 333 let maybe_binding = find_node_at_offset::<ast::BindPat>(syntax, offset).or_else(|| {
330 .or_else(|| { 334 let name_ref = find_node_at_offset::<ast::NameRef>(syntax, offset)?;
331 let name_ref = find_node_at_offset::<ast::NameRef>(syntax, offset)?; 335 let resolved = resolve_local_name(&self.db, file_id, name_ref)?;
332 let resolved = resolve_local_name(&self.db, file_id, name_ref)?; 336 find_node_at_offset::<ast::BindPat>(syntax, resolved.1.end())
333 find_node_at_offset::<ast::BindPat>(syntax, resolved.1.end()) 337 });
334 });
335 338
336 let binding = match maybe_binding { 339 let binding = match maybe_binding {
337 None => return Vec::new(), 340 None => return Vec::new(),
@@ -341,8 +344,11 @@ impl AnalysisImpl {
341 let decl = DeclarationDescriptor::new(binding); 344 let decl = DeclarationDescriptor::new(binding);
342 345
343 let mut ret = vec![(file_id, decl.range)]; 346 let mut ret = vec![(file_id, decl.range)];
344 ret.extend(decl.find_all_refs().into_iter() 347 ret.extend(
345 .map(|ref_desc| (file_id, ref_desc.range ))); 348 decl.find_all_refs()
349 .into_iter()
350 .map(|ref_desc| (file_id, ref_desc.range)),
351 );
346 352
347 ret 353 ret
348 } 354 }
@@ -526,7 +532,8 @@ impl AnalysisImpl {
526 Some(id) => id, 532 Some(id) => id,
527 None => return Vec::new(), 533 None => return Vec::new(),
528 }; 534 };
529 module_id.child(module_tree, name.as_str()) 535 module_id
536 .child(module_tree, name.as_str())
530 .map(|it| it.file_id(module_tree)) 537 .map(|it| it.file_id(module_tree))
531 .into_iter() 538 .into_iter()
532 .collect() 539 .collect()
diff --git a/crates/ra_analysis/src/input.rs b/crates/ra_analysis/src/input.rs
index b89b45133..ba8a17fd5 100644
--- a/crates/ra_analysis/src/input.rs
+++ b/crates/ra_analysis/src/input.rs
@@ -1,12 +1,9 @@
1use std::{ 1use std::{fmt, sync::Arc};
2 sync::Arc,
3 fmt,
4};
5 2
6use salsa;
7use rustc_hash::FxHashSet;
8use relative_path::RelativePath; 3use relative_path::RelativePath;
9use rustc_hash::FxHashMap; 4use rustc_hash::FxHashMap;
5use rustc_hash::FxHashSet;
6use salsa;
10 7
11use crate::{symbol_index::SymbolIndex, FileResolverImp}; 8use crate::{symbol_index::SymbolIndex, FileResolverImp};
12 9
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index e75411ec9..32aa7a1fd 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -6,23 +6,20 @@ extern crate relative_path;
6extern crate rustc_hash; 6extern crate rustc_hash;
7extern crate salsa; 7extern crate salsa;
8 8
9mod input; 9mod completion;
10mod db; 10mod db;
11mod descriptors; 11mod descriptors;
12mod imp; 12mod imp;
13mod input;
14pub mod mock_analysis;
13mod symbol_index; 15mod symbol_index;
14mod completion;
15mod syntax_ptr; 16mod syntax_ptr;
16pub mod mock_analysis;
17 17
18use std::{ 18use std::{fmt, sync::Arc};
19 fmt,
20 sync::Arc,
21};
22 19
23use ra_syntax::{AtomEdit, File, TextRange, TextUnit}; 20use ra_syntax::{AtomEdit, File, TextRange, TextUnit};
24use relative_path::RelativePathBuf;
25use rayon::prelude::*; 21use rayon::prelude::*;
22use relative_path::RelativePathBuf;
26 23
27use crate::{ 24use crate::{
28 imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp}, 25 imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp},
@@ -30,13 +27,12 @@ use crate::{
30}; 27};
31 28
32pub use crate::{ 29pub use crate::{
33 descriptors::function::FnDescriptor,
34 completion::CompletionItem, 30 completion::CompletionItem,
35 input::{FileId, FileResolver, CrateGraph, CrateId}, 31 descriptors::function::FnDescriptor,
32 input::{CrateGraph, CrateId, FileId, FileResolver},
36}; 33};
37pub use ra_editor::{ 34pub use ra_editor::{
38 FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, 35 FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, RunnableKind, StructureNode,
39 RunnableKind, StructureNode,
40}; 36};
41 37
42#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 38#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
@@ -50,8 +46,7 @@ impl std::fmt::Display for Canceled {
50 } 46 }
51} 47}
52 48
53impl std::error::Error for Canceled { 49impl std::error::Error for Canceled {}
54}
55 50
56#[derive(Default)] 51#[derive(Default)]
57pub struct AnalysisChange { 52pub struct AnalysisChange {
@@ -76,7 +71,6 @@ impl fmt::Debug for AnalysisChange {
76 } 71 }
77} 72}
78 73
79
80impl AnalysisChange { 74impl AnalysisChange {
81 pub fn new() -> AnalysisChange { 75 pub fn new() -> AnalysisChange {
82 AnalysisChange::default() 76 AnalysisChange::default()
@@ -251,12 +245,15 @@ impl Analysis {
251 pub fn approximately_resolve_symbol( 245 pub fn approximately_resolve_symbol(
252 &self, 246 &self,
253 file_id: FileId, 247 file_id: FileId,
254 offset: TextUnit 248 offset: TextUnit,
255 ) -> Cancelable<Vec<(FileId, FileSymbol)>> { 249 ) -> Cancelable<Vec<(FileId, FileSymbol)>> {
256 self.imp 250 self.imp.approximately_resolve_symbol(file_id, offset)
257 .approximately_resolve_symbol(file_id, offset)
258 } 251 }
259 pub fn find_all_refs(&self, file_id: FileId, offset: TextUnit, ) -> Cancelable<Vec<(FileId, TextRange)>> { 252 pub fn find_all_refs(
253 &self,
254 file_id: FileId,
255 offset: TextUnit,
256 ) -> Cancelable<Vec<(FileId, TextRange)>> {
260 Ok(self.imp.find_all_refs(file_id, offset)) 257 Ok(self.imp.find_all_refs(file_id, offset))
261 } 258 }
262 pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { 259 pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> {
@@ -276,7 +273,11 @@ impl Analysis {
276 let file = self.imp.file_syntax(file_id); 273 let file = self.imp.file_syntax(file_id);
277 Ok(ra_editor::highlight(&file)) 274 Ok(ra_editor::highlight(&file))
278 } 275 }
279 pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> { 276 pub fn completions(
277 &self,
278 file_id: FileId,
279 offset: TextUnit,
280 ) -> Cancelable<Option<Vec<CompletionItem>>> {
280 self.imp.completions(file_id, offset) 281 self.imp.completions(file_id, offset)
281 } 282 }
282 pub fn assists(&self, file_id: FileId, range: TextRange) -> Cancelable<Vec<SourceChange>> { 283 pub fn assists(&self, file_id: FileId, range: TextRange) -> Cancelable<Vec<SourceChange>> {
@@ -307,7 +308,11 @@ impl LibraryData {
307 let file = File::parse(text); 308 let file = File::parse(text);
308 (*file_id, file) 309 (*file_id, file)
309 })); 310 }));
310 LibraryData { files, file_resolver: FileResolverImp::new(file_resolver), symbol_index } 311 LibraryData {
312 files,
313 file_resolver: FileResolverImp::new(file_resolver),
314 symbol_index,
315 }
311 } 316 }
312} 317}
313 318
diff --git a/crates/ra_analysis/src/mock_analysis.rs b/crates/ra_analysis/src/mock_analysis.rs
index f72911192..76100f548 100644
--- a/crates/ra_analysis/src/mock_analysis.rs
+++ b/crates/ra_analysis/src/mock_analysis.rs
@@ -1,13 +1,10 @@
1
2use std::sync::Arc; 1use std::sync::Arc;
3 2
4use relative_path::{RelativePath, RelativePathBuf};
5use ra_syntax::TextUnit; 3use ra_syntax::TextUnit;
4use relative_path::{RelativePath, RelativePathBuf};
6use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; 5use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER};
7 6
8use crate::{ 7use crate::{Analysis, AnalysisChange, AnalysisHost, FileId, FileResolver};
9 AnalysisChange, Analysis, AnalysisHost, FileId, FileResolver,
10};
11 8
12#[derive(Debug)] 9#[derive(Debug)]
13pub struct FilePosition { 10pub struct FilePosition {
@@ -51,7 +48,10 @@ impl MockAnalysis {
51 let mut res = MockAnalysis::new(); 48 let mut res = MockAnalysis::new();
52 for entry in parse_fixture(fixture) { 49 for entry in parse_fixture(fixture) {
53 if entry.text.contains(CURSOR_MARKER) { 50 if entry.text.contains(CURSOR_MARKER) {
54 assert!(position.is_none(), "only one marker (<|>) per fixture is allowed"); 51 assert!(
52 position.is_none(),
53 "only one marker (<|>) per fixture is allowed"
54 );
55 position = Some(res.add_file_with_position(&entry.meta, &entry.text)); 55 position = Some(res.add_file_with_position(&entry.meta, &entry.text));
56 } else { 56 } else {
57 res.add_file(&entry.meta, &entry.text); 57 res.add_file(&entry.meta, &entry.text);
@@ -73,7 +73,10 @@ impl MockAnalysis {
73 FilePosition { file_id, offset } 73 FilePosition { file_id, offset }
74 } 74 }
75 pub fn id_of(&self, path: &str) -> FileId { 75 pub fn id_of(&self, path: &str) -> FileId {
76 let (idx, _) = self.files.iter().enumerate() 76 let (idx, _) = self
77 .files
78 .iter()
79 .enumerate()
77 .find(|(_, (p, _text))| path == p) 80 .find(|(_, (p, _text))| path == p)
78 .expect("no file in this mock"); 81 .expect("no file in this mock");
79 FileId(idx as u32 + 1) 82 FileId(idx as u32 + 1)
diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs
index 5f302cbda..b57ad5d33 100644
--- a/crates/ra_analysis/src/symbol_index.rs
+++ b/crates/ra_analysis/src/symbol_index.rs
@@ -57,10 +57,7 @@ impl SymbolIndex {
57} 57}
58 58
59impl Query { 59impl Query {
60 pub(crate) fn search( 60 pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<(FileId, FileSymbol)> {
61 self,
62 indices: &[Arc<SymbolIndex>],
63 ) -> Vec<(FileId, FileSymbol)> {
64 let mut op = fst::map::OpBuilder::new(); 61 let mut op = fst::map::OpBuilder::new();
65 for file_symbols in indices.iter() { 62 for file_symbols in indices.iter() {
66 let automaton = fst::automaton::Subsequence::new(&self.lowercased); 63 let automaton = fst::automaton::Subsequence::new(&self.lowercased);
diff --git a/crates/ra_analysis/src/syntax_ptr.rs b/crates/ra_analysis/src/syntax_ptr.rs
index c3c904633..612f75cd9 100644
--- a/crates/ra_analysis/src/syntax_ptr.rs
+++ b/crates/ra_analysis/src/syntax_ptr.rs
@@ -1,12 +1,12 @@
1use std::marker::PhantomData; 1use std::marker::PhantomData;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 File, TextRange, SyntaxKind, SyntaxNode, SyntaxNodeRef,
5 ast::{self, AstNode}, 4 ast::{self, AstNode},
5 File, SyntaxKind, SyntaxNode, SyntaxNodeRef, TextRange,
6}; 6};
7 7
8use crate::FileId;
9use crate::db::SyntaxDatabase; 8use crate::db::SyntaxDatabase;
9use crate::FileId;
10 10
11salsa::query_group! { 11salsa::query_group! {
12 pub(crate) trait SyntaxPtrDatabase: SyntaxDatabase { 12 pub(crate) trait SyntaxPtrDatabase: SyntaxDatabase {
@@ -52,12 +52,10 @@ trait ToAst {
52impl<'a> ToAst for &'a OwnedAst<ast::FnDef<'static>> { 52impl<'a> ToAst for &'a OwnedAst<ast::FnDef<'static>> {
53 type Ast = ast::FnDef<'a>; 53 type Ast = ast::FnDef<'a>;
54 fn to_ast(self) -> ast::FnDef<'a> { 54 fn to_ast(self) -> ast::FnDef<'a> {
55 ast::FnDef::cast(self.syntax.borrowed()) 55 ast::FnDef::cast(self.syntax.borrowed()).unwrap()
56 .unwrap()
57 } 56 }
58} 57}
59 58
60
61/// A pionter to a syntax node inside a file. 59/// A pionter to a syntax node inside a file.
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 60#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
63pub(crate) struct LocalSyntaxPtr { 61pub(crate) struct LocalSyntaxPtr {
@@ -79,22 +77,29 @@ impl LocalSyntaxPtr {
79 if curr.range() == self.range && curr.kind() == self.kind { 77 if curr.range() == self.range && curr.kind() == self.kind {
80 return curr.owned(); 78 return curr.owned();
81 } 79 }
82 curr = curr.children() 80 curr = curr
81 .children()
83 .find(|it| self.range.is_subrange(&it.range())) 82 .find(|it| self.range.is_subrange(&it.range()))
84 .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self)) 83 .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
85 } 84 }
86 } 85 }
87 86
88 pub(crate) fn into_global(self, file_id: FileId) -> SyntaxPtr { 87 pub(crate) fn into_global(self, file_id: FileId) -> SyntaxPtr {
89 SyntaxPtr { file_id, local: self} 88 SyntaxPtr {
89 file_id,
90 local: self,
91 }
90 } 92 }
91} 93}
92 94
93
94#[test] 95#[test]
95fn test_local_syntax_ptr() { 96fn test_local_syntax_ptr() {
96 let file = File::parse("struct Foo { f: u32, }"); 97 let file = File::parse("struct Foo { f: u32, }");
97 let field = file.syntax().descendants().find_map(ast::NamedFieldDef::cast).unwrap(); 98 let field = file
99 .syntax()
100 .descendants()
101 .find_map(ast::NamedFieldDef::cast)
102 .unwrap();
98 let ptr = LocalSyntaxPtr::new(field.syntax()); 103 let ptr = LocalSyntaxPtr::new(field.syntax());
99 let field_syntax = ptr.resolve(&file); 104 let field_syntax = ptr.resolve(&file);
100 assert_eq!(field.syntax(), field_syntax); 105 assert_eq!(field.syntax(), field_syntax);
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs
index 22d27cdbe..c2754c8e4 100644
--- a/crates/ra_analysis/tests/tests.rs
+++ b/crates/ra_analysis/tests/tests.rs
@@ -5,42 +5,53 @@ extern crate relative_path;
5extern crate rustc_hash; 5extern crate rustc_hash;
6extern crate test_utils; 6extern crate test_utils;
7 7
8use ra_syntax::{TextRange}; 8use ra_syntax::TextRange;
9use test_utils::{assert_eq_dbg}; 9use test_utils::assert_eq_dbg;
10 10
11use ra_analysis::{ 11use ra_analysis::{
12 mock_analysis::{analysis_and_position, single_file, single_file_with_position, MockAnalysis},
12 AnalysisChange, CrateGraph, FileId, FnDescriptor, 13 AnalysisChange, CrateGraph, FileId, FnDescriptor,
13 mock_analysis::{MockAnalysis, single_file, single_file_with_position, analysis_and_position},
14}; 14};
15 15
16fn get_signature(text: &str) -> (FnDescriptor, Option<usize>) { 16fn get_signature(text: &str) -> (FnDescriptor, Option<usize>) {
17 let (analysis, position) = single_file_with_position(text); 17 let (analysis, position) = single_file_with_position(text);
18 analysis.resolve_callable(position.file_id, position.offset).unwrap().unwrap() 18 analysis
19 .resolve_callable(position.file_id, position.offset)
20 .unwrap()
21 .unwrap()
19} 22}
20 23
21#[test] 24#[test]
22fn test_resolve_module() { 25fn test_resolve_module() {
23 let (analysis, pos) = analysis_and_position(" 26 let (analysis, pos) = analysis_and_position(
27 "
24 //- /lib.rs 28 //- /lib.rs
25 mod <|>foo; 29 mod <|>foo;
26 //- /foo.rs 30 //- /foo.rs
27 // empty 31 // empty
28 "); 32 ",
33 );
29 34
30 let symbols = analysis.approximately_resolve_symbol(pos.file_id, pos.offset).unwrap(); 35 let symbols = analysis
36 .approximately_resolve_symbol(pos.file_id, pos.offset)
37 .unwrap();
31 assert_eq_dbg( 38 assert_eq_dbg(
32 r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, 39 r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#,
33 &symbols, 40 &symbols,
34 ); 41 );
35 42
36 let (analysis, pos) = analysis_and_position(" 43 let (analysis, pos) = analysis_and_position(
44 "
37 //- /lib.rs 45 //- /lib.rs
38 mod <|>foo; 46 mod <|>foo;
39 //- /foo/mod.rs 47 //- /foo/mod.rs
40 // empty 48 // empty
41 "); 49 ",
50 );
42 51
43 let symbols = analysis.approximately_resolve_symbol(pos.file_id, pos.offset).unwrap(); 52 let symbols = analysis
53 .approximately_resolve_symbol(pos.file_id, pos.offset)
54 .unwrap();
44 assert_eq_dbg( 55 assert_eq_dbg(
45 r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, 56 r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#,
46 &symbols, 57 &symbols,
@@ -73,12 +84,14 @@ fn test_unresolved_module_diagnostic_no_diag_for_inline_mode() {
73 84
74#[test] 85#[test]
75fn test_resolve_parent_module() { 86fn test_resolve_parent_module() {
76 let (analysis, pos) = analysis_and_position(" 87 let (analysis, pos) = analysis_and_position(
88 "
77 //- /lib.rs 89 //- /lib.rs
78 mod foo; 90 mod foo;
79 //- /foo.rs 91 //- /foo.rs
80 <|>// empty 92 <|>// empty
81 "); 93 ",
94 );
82 let symbols = analysis.parent_module(pos.file_id).unwrap(); 95 let symbols = analysis.parent_module(pos.file_id).unwrap();
83 assert_eq_dbg( 96 assert_eq_dbg(
84 r#"[(FileId(1), FileSymbol { name: "foo", node_range: [0; 8), kind: MODULE })]"#, 97 r#"[(FileId(1), FileSymbol { name: "foo", node_range: [0; 8), kind: MODULE })]"#,
@@ -88,12 +101,14 @@ fn test_resolve_parent_module() {
88 101
89#[test] 102#[test]
90fn test_resolve_crate_root() { 103fn test_resolve_crate_root() {
91 let mock = MockAnalysis::with_files(" 104 let mock = MockAnalysis::with_files(
105 "
92 //- /lib.rs 106 //- /lib.rs
93 mod foo; 107 mod foo;
94 //- /foo.rs 108 //- /foo.rs
95 // emtpy <|> 109 // emtpy <|>
96 "); 110 ",
111 );
97 let root_file = mock.id_of("/lib.rs"); 112 let root_file = mock.id_of("/lib.rs");
98 let mod_file = mock.id_of("/foo.rs"); 113 let mod_file = mock.id_of("/foo.rs");
99 let mut host = mock.analysis_host(); 114 let mut host = mock.analysis_host();
@@ -245,8 +260,10 @@ pub fn do() {
245 assert_eq!(desc.ret_type, Some("-> i32".to_string())); 260 assert_eq!(desc.ret_type, Some("-> i32".to_string()));
246 assert_eq!(param, Some(0)); 261 assert_eq!(param, Some(0));
247 assert_eq!(desc.label, "pub fn add_one(x: i32) -> i32".to_string()); 262 assert_eq!(desc.label, "pub fn add_one(x: i32) -> i32".to_string());
248 assert_eq!(desc.doc, Some( 263 assert_eq!(
249r#"Adds one to the number given. 264 desc.doc,
265 Some(
266 r#"Adds one to the number given.
250 267
251# Examples 268# Examples
252 269
@@ -254,7 +271,10 @@ r#"Adds one to the number given.
254let five = 5; 271let five = 5;
255 272
256assert_eq!(6, my_crate::add_one(5)); 273assert_eq!(6, my_crate::add_one(5));
257```"#.into())); 274```"#
275 .into()
276 )
277 );
258} 278}
259 279
260#[test] 280#[test]
@@ -280,15 +300,18 @@ impl addr {
280pub fn do_it() { 300pub fn do_it() {
281 addr {}; 301 addr {};
282 addr::add_one(<|>); 302 addr::add_one(<|>);
283}"#); 303}"#,
304 );
284 305
285 assert_eq!(desc.name, "add_one".to_string()); 306 assert_eq!(desc.name, "add_one".to_string());
286 assert_eq!(desc.params, vec!["x".to_string()]); 307 assert_eq!(desc.params, vec!["x".to_string()]);
287 assert_eq!(desc.ret_type, Some("-> i32".to_string())); 308 assert_eq!(desc.ret_type, Some("-> i32".to_string()));
288 assert_eq!(param, Some(0)); 309 assert_eq!(param, Some(0));
289 assert_eq!(desc.label, "pub fn add_one(x: i32) -> i32".to_string()); 310 assert_eq!(desc.label, "pub fn add_one(x: i32) -> i32".to_string());
290 assert_eq!(desc.doc, Some( 311 assert_eq!(
291r#"Adds one to the number given. 312 desc.doc,
313 Some(
314 r#"Adds one to the number given.
292 315
293# Examples 316# Examples
294 317
@@ -296,7 +319,10 @@ r#"Adds one to the number given.
296let five = 5; 319let five = 5;
297 320
298assert_eq!(6, my_crate::add_one(5)); 321assert_eq!(6, my_crate::add_one(5));
299```"#.into())); 322```"#
323 .into()
324 )
325 );
300} 326}
301 327
302#[test] 328#[test]
@@ -329,22 +355,32 @@ pub fn foo() {
329 r.finished(<|>); 355 r.finished(<|>);
330} 356}
331 357
332"#); 358"#,
359 );
333 360
334 assert_eq!(desc.name, "finished".to_string()); 361 assert_eq!(desc.name, "finished".to_string());
335 assert_eq!(desc.params, vec!["&mut self".to_string(), "ctx".to_string()]); 362 assert_eq!(
363 desc.params,
364 vec!["&mut self".to_string(), "ctx".to_string()]
365 );
336 assert_eq!(desc.ret_type, None); 366 assert_eq!(desc.ret_type, None);
337 assert_eq!(param, Some(1)); 367 assert_eq!(param, Some(1));
338 assert_eq!(desc.doc, Some( 368 assert_eq!(
339r#"Method is called when writer finishes. 369 desc.doc,
340 370 Some(
341By default this method stops actor's `Context`."#.into())); 371 r#"Method is called when writer finishes.
372
373By default this method stops actor's `Context`."#
374 .into()
375 )
376 );
342} 377}
343 378
344
345fn get_all_refs(text: &str) -> Vec<(FileId, TextRange)> { 379fn get_all_refs(text: &str) -> Vec<(FileId, TextRange)> {
346 let (analysis, position) = single_file_with_position(text); 380 let (analysis, position) = single_file_with_position(text);
347 analysis.find_all_refs(position.file_id, position.offset).unwrap() 381 analysis
382 .find_all_refs(position.file_id, position.offset)
383 .unwrap()
348} 384}
349 385
350#[test] 386#[test]
@@ -390,14 +426,19 @@ fn test_find_all_refs_for_fn_param() {
390 426
391#[test] 427#[test]
392fn test_complete_crate_path() { 428fn test_complete_crate_path() {
393 let (analysis, position) = analysis_and_position(" 429 let (analysis, position) = analysis_and_position(
430 "
394 //- /lib.rs 431 //- /lib.rs
395 mod foo; 432 mod foo;
396 struct Spam; 433 struct Spam;
397 //- /foo.rs 434 //- /foo.rs
398 use crate::Sp<|> 435 use crate::Sp<|>
399 "); 436 ",
400 let completions = analysis.completions(position.file_id, position.offset).unwrap().unwrap(); 437 );
438 let completions = analysis
439 .completions(position.file_id, position.offset)
440 .unwrap()
441 .unwrap();
401 assert_eq_dbg( 442 assert_eq_dbg(
402 r#"[CompletionItem { label: "foo", lookup: None, snippet: None }, 443 r#"[CompletionItem { label: "foo", lookup: None, snippet: None },
403 CompletionItem { label: "Spam", lookup: None, snippet: None }]"#, 444 CompletionItem { label: "Spam", lookup: None, snippet: None }]"#,