diff options
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r-- | crates/ra_ide_api/src/completion.rs | 5 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_dot.rs | 20 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_fn_param.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_scope.rs | 21 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/snapshots/completion_item__completes_prelude.snap | 54 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/snapshots/completion_item__method_attr_filtering.snap | 26 | ||||
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 8 | ||||
-rw-r--r-- | crates/ra_ide_api/src/hover.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/impls.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/lib.rs | 13 | ||||
-rw-r--r-- | crates/ra_ide_api/src/mock_analysis.rs | 8 | ||||
-rw-r--r-- | crates/ra_ide_api/src/navigation_target.rs | 11 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide_api/src/symbol_index.rs | 64 |
14 files changed, 202 insertions, 44 deletions
diff --git a/crates/ra_ide_api/src/completion.rs b/crates/ra_ide_api/src/completion.rs index 83c243944..4a38d62bb 100644 --- a/crates/ra_ide_api/src/completion.rs +++ b/crates/ra_ide_api/src/completion.rs | |||
@@ -30,7 +30,7 @@ pub use crate::completion::completion_item::{CompletionItem, CompletionItemKind, | |||
30 | /// incomplete and can look really weird. | 30 | /// incomplete and can look really weird. |
31 | /// | 31 | /// |
32 | /// Once the context is collected, we run a series of completion routines which | 32 | /// Once the context is collected, we run a series of completion routines which |
33 | /// look at the context and produce completion items. One subtelty about this | 33 | /// look at the context and produce completion items. One subtlety about this |
34 | /// phase is that completion engine should not filter by the substring which is | 34 | /// phase is that completion engine should not filter by the substring which is |
35 | /// already present, it should give all possible variants for the identifier at | 35 | /// already present, it should give all possible variants for the identifier at |
36 | /// the caret. In other words, for | 36 | /// the caret. In other words, for |
@@ -71,6 +71,7 @@ pub fn function_label(node: &ast::FnDef) -> Option<String> { | |||
71 | .children() | 71 | .children() |
72 | .filter(|child| !child.range().is_subrange(&body_range)) // Filter out body | 72 | .filter(|child| !child.range().is_subrange(&body_range)) // Filter out body |
73 | .filter(|child| ast::Comment::cast(child).is_none()) // Filter out comments | 73 | .filter(|child| ast::Comment::cast(child).is_none()) // Filter out comments |
74 | .filter(|child| ast::Attr::cast(child).is_none()) // Filter out attributes | ||
74 | .map(|node| node.text().to_string()) | 75 | .map(|node| node.text().to_string()) |
75 | .collect(); | 76 | .collect(); |
76 | label | 77 | label |
@@ -86,6 +87,7 @@ pub fn const_label(node: &ast::ConstDef) -> String { | |||
86 | .syntax() | 87 | .syntax() |
87 | .children() | 88 | .children() |
88 | .filter(|child| ast::Comment::cast(child).is_none()) | 89 | .filter(|child| ast::Comment::cast(child).is_none()) |
90 | .filter(|child| ast::Attr::cast(child).is_none()) | ||
89 | .map(|node| node.text().to_string()) | 91 | .map(|node| node.text().to_string()) |
90 | .collect(); | 92 | .collect(); |
91 | 93 | ||
@@ -97,6 +99,7 @@ pub fn type_label(node: &ast::TypeDef) -> String { | |||
97 | .syntax() | 99 | .syntax() |
98 | .children() | 100 | .children() |
99 | .filter(|child| ast::Comment::cast(child).is_none()) | 101 | .filter(|child| ast::Comment::cast(child).is_none()) |
102 | .filter(|child| ast::Attr::cast(child).is_none()) | ||
100 | .map(|node| node.text().to_string()) | 103 | .map(|node| node.text().to_string()) |
101 | .collect(); | 104 | .collect(); |
102 | 105 | ||
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index a673dbdcf..be839345f 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs | |||
@@ -180,6 +180,26 @@ mod tests { | |||
180 | } | 180 | } |
181 | 181 | ||
182 | #[test] | 182 | #[test] |
183 | fn test_method_attr_filtering() { | ||
184 | check_ref_completion( | ||
185 | "method_attr_filtering", | ||
186 | r" | ||
187 | struct A {} | ||
188 | impl A { | ||
189 | #[inline] | ||
190 | fn the_method(&self) { | ||
191 | let x = 1; | ||
192 | let y = 2; | ||
193 | } | ||
194 | } | ||
195 | fn foo(a: A) { | ||
196 | a.<|> | ||
197 | } | ||
198 | ", | ||
199 | ); | ||
200 | } | ||
201 | |||
202 | #[test] | ||
183 | fn test_tuple_field_completion() { | 203 | fn test_tuple_field_completion() { |
184 | check_ref_completion( | 204 | check_ref_completion( |
185 | "tuple_field_completion", | 205 | "tuple_field_completion", |
diff --git a/crates/ra_ide_api/src/completion/complete_fn_param.rs b/crates/ra_ide_api/src/completion/complete_fn_param.rs index 43532226f..4d6416284 100644 --- a/crates/ra_ide_api/src/completion/complete_fn_param.rs +++ b/crates/ra_ide_api/src/completion/complete_fn_param.rs | |||
@@ -7,7 +7,7 @@ use rustc_hash::FxHashMap; | |||
7 | 7 | ||
8 | use crate::completion::{CompletionContext, Completions, CompletionKind, CompletionItem}; | 8 | use crate::completion::{CompletionContext, Completions, CompletionKind, CompletionItem}; |
9 | 9 | ||
10 | /// Complete repeated parametes, both name and type. For example, if all | 10 | /// Complete repeated parameters, both name and type. For example, if all |
11 | /// functions in a file have a `spam: &mut Spam` parameter, a completion with | 11 | /// functions in a file have a `spam: &mut Spam` parameter, a completion with |
12 | /// `spam: &mut Spam` insert text/label and `spam` lookup string will be | 12 | /// `spam: &mut Spam` insert text/label and `spam` lookup string will be |
13 | /// suggested. | 13 | /// suggested. |
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index 445788407..eeaf26d93 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs | |||
@@ -4,7 +4,7 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { | |||
4 | if !ctx.is_trivial_path { | 4 | if !ctx.is_trivial_path { |
5 | return; | 5 | return; |
6 | } | 6 | } |
7 | let names = ctx.resolver.all_names(); | 7 | let names = ctx.resolver.all_names(ctx.db); |
8 | 8 | ||
9 | names.into_iter().for_each(|(name, res)| { | 9 | names.into_iter().for_each(|(name, res)| { |
10 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) | 10 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) |
@@ -165,4 +165,23 @@ mod tests { | |||
165 | fn completes_self_in_methods() { | 165 | fn completes_self_in_methods() { |
166 | check_reference_completion("self_in_methods", r"impl S { fn foo(&self) { <|> } }") | 166 | check_reference_completion("self_in_methods", r"impl S { fn foo(&self) { <|> } }") |
167 | } | 167 | } |
168 | |||
169 | #[test] | ||
170 | fn completes_prelude() { | ||
171 | check_reference_completion( | ||
172 | "completes_prelude", | ||
173 | " | ||
174 | //- /main.rs | ||
175 | fn foo() { let x: <|> } | ||
176 | |||
177 | //- /std/lib.rs | ||
178 | #[prelude_import] | ||
179 | use prelude::*; | ||
180 | |||
181 | mod prelude { | ||
182 | struct Option; | ||
183 | } | ||
184 | ", | ||
185 | ); | ||
186 | } | ||
168 | } | 187 | } |
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_prelude.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_prelude.snap new file mode 100644 index 000000000..2b5a1a8ea --- /dev/null +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_prelude.snap | |||
@@ -0,0 +1,54 @@ | |||
1 | --- | ||
2 | created: "2019-02-13T19:52:43.734834624Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_ide_api/src/completion/completion_item.rs | ||
5 | expression: kind_completions | ||
6 | --- | ||
7 | [ | ||
8 | CompletionItem { | ||
9 | completion_kind: Reference, | ||
10 | label: "Option", | ||
11 | kind: Some( | ||
12 | Struct | ||
13 | ), | ||
14 | detail: None, | ||
15 | documentation: None, | ||
16 | lookup: None, | ||
17 | insert_text: None, | ||
18 | insert_text_format: PlainText, | ||
19 | source_range: [18; 18), | ||
20 | text_edit: None | ||
21 | }, | ||
22 | CompletionItem { | ||
23 | completion_kind: Reference, | ||
24 | label: "foo", | ||
25 | kind: Some( | ||
26 | Function | ||
27 | ), | ||
28 | detail: Some( | ||
29 | "fn foo()" | ||
30 | ), | ||
31 | documentation: None, | ||
32 | lookup: None, | ||
33 | insert_text: Some( | ||
34 | "foo()$0" | ||
35 | ), | ||
36 | insert_text_format: Snippet, | ||
37 | source_range: [18; 18), | ||
38 | text_edit: None | ||
39 | }, | ||
40 | CompletionItem { | ||
41 | completion_kind: Reference, | ||
42 | label: "std", | ||
43 | kind: Some( | ||
44 | Module | ||
45 | ), | ||
46 | detail: None, | ||
47 | documentation: None, | ||
48 | lookup: None, | ||
49 | insert_text: None, | ||
50 | insert_text_format: PlainText, | ||
51 | source_range: [18; 18), | ||
52 | text_edit: None | ||
53 | } | ||
54 | ] | ||
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__method_attr_filtering.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__method_attr_filtering.snap new file mode 100644 index 000000000..46f9fa971 --- /dev/null +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__method_attr_filtering.snap | |||
@@ -0,0 +1,26 @@ | |||
1 | --- | ||
2 | created: "2019-02-12T18:32:09.428929418Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_ide_api/src/completion/completion_item.rs | ||
5 | expression: kind_completions | ||
6 | --- | ||
7 | [ | ||
8 | CompletionItem { | ||
9 | completion_kind: Reference, | ||
10 | label: "the_method", | ||
11 | kind: Some( | ||
12 | Method | ||
13 | ), | ||
14 | detail: Some( | ||
15 | "fn the_method(&self)" | ||
16 | ), | ||
17 | documentation: None, | ||
18 | lookup: None, | ||
19 | insert_text: Some( | ||
20 | "the_method()$0" | ||
21 | ), | ||
22 | insert_text_format: Snippet, | ||
23 | source_range: [249; 249), | ||
24 | text_edit: None | ||
25 | } | ||
26 | ] | ||
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 413720960..96ed8c8e9 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -93,10 +93,10 @@ pub(crate) fn reference_definition( | |||
93 | return Exact(nav); | 93 | return Exact(nav); |
94 | } | 94 | } |
95 | Some(Resolution::GenericParam(..)) => { | 95 | Some(Resolution::GenericParam(..)) => { |
96 | // TODO go to the generic param def | 96 | // TODO: go to the generic param def |
97 | } | 97 | } |
98 | Some(Resolution::SelfType(_impl_block)) => { | 98 | Some(Resolution::SelfType(_impl_block)) => { |
99 | // TODO go to the implemented type | 99 | // TODO: go to the implemented type |
100 | } | 100 | } |
101 | None => {} | 101 | None => {} |
102 | } | 102 | } |
@@ -133,8 +133,8 @@ mod tests { | |||
133 | 133 | ||
134 | use crate::mock_analysis::analysis_and_position; | 134 | use crate::mock_analysis::analysis_and_position; |
135 | 135 | ||
136 | fn check_goto(fixuture: &str, expected: &str) { | 136 | fn check_goto(fixture: &str, expected: &str) { |
137 | let (analysis, pos) = analysis_and_position(fixuture); | 137 | let (analysis, pos) = analysis_and_position(fixture); |
138 | 138 | ||
139 | let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info; | 139 | let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info; |
140 | assert_eq!(navs.len(), 1); | 140 | assert_eq!(navs.len(), 1); |
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 60b81567c..0888ab6de 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs | |||
@@ -71,8 +71,8 @@ pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> { | |||
71 | } | 71 | } |
72 | } | 72 | } |
73 | 73 | ||
74 | // FIXME: this should not really use navigation target. Rather, approximatelly | 74 | // FIXME: this should not really use navigation target. Rather, approximately |
75 | // resovled symbol should return a `DefId`. | 75 | // resolved symbol should return a `DefId`. |
76 | fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Option<String> { | 76 | fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Option<String> { |
77 | match (nav.description(db), nav.docs(db)) { | 77 | match (nav.description(db), nav.docs(db)) { |
78 | (Some(desc), Some(docs)) => Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs), | 78 | (Some(desc), Some(docs)) => Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs), |
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs index 444c4aeb2..681bd808d 100644 --- a/crates/ra_ide_api/src/impls.rs +++ b/crates/ra_ide_api/src/impls.rs | |||
@@ -78,8 +78,8 @@ fn impls_for_trait( | |||
78 | mod tests { | 78 | mod tests { |
79 | use crate::mock_analysis::analysis_and_position; | 79 | use crate::mock_analysis::analysis_and_position; |
80 | 80 | ||
81 | fn check_goto(fixuture: &str, expected: &[&str]) { | 81 | fn check_goto(fixture: &str, expected: &[&str]) { |
82 | let (analysis, pos) = analysis_and_position(fixuture); | 82 | let (analysis, pos) = analysis_and_position(fixture); |
83 | 83 | ||
84 | let navs = analysis.goto_implementation(pos).unwrap().unwrap().info; | 84 | let navs = analysis.goto_implementation(pos).unwrap().unwrap().info; |
85 | assert_eq!(navs.len(), expected.len()); | 85 | assert_eq!(navs.len(), expected.len()); |
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index 2d090d9b4..d77a56ce8 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs | |||
@@ -7,7 +7,7 @@ | |||
7 | //! However, IDE specific bits of the analysis (most notably completion) happen | 7 | //! However, IDE specific bits of the analysis (most notably completion) happen |
8 | //! in this crate. | 8 | //! in this crate. |
9 | //! | 9 | //! |
10 | //! The sibling `ra_ide_api_light` handles thouse bits of IDE functionality | 10 | //! The sibling `ra_ide_api_light` handles those bits of IDE functionality |
11 | //! which are restricted to a single file and need only syntax. | 11 | //! which are restricted to a single file and need only syntax. |
12 | 12 | ||
13 | // For proving that RootDatabase is RefUnwindSafe. | 13 | // For proving that RootDatabase is RefUnwindSafe. |
@@ -62,12 +62,13 @@ pub use ra_ide_api_light::{ | |||
62 | LineIndex, LineCol, translate_offset_with_edit, | 62 | LineIndex, LineCol, translate_offset_with_edit, |
63 | }; | 63 | }; |
64 | pub use ra_db::{ | 64 | pub use ra_db::{ |
65 | Canceled, CrateGraph, CrateId, FileId, FilePosition, FileRange, SourceRootId | 65 | Canceled, CrateGraph, CrateId, FileId, FilePosition, FileRange, SourceRootId, |
66 | Edition | ||
66 | }; | 67 | }; |
67 | pub use hir::Documentation; | 68 | pub use hir::Documentation; |
68 | 69 | ||
69 | // We use jemalloc mainly to get heap usage statistics, actual performance | 70 | // We use jemalloc mainly to get heap usage statistics, actual performance |
70 | // differnece is not measures. | 71 | // difference is not measures. |
71 | #[cfg(feature = "jemalloc")] | 72 | #[cfg(feature = "jemalloc")] |
72 | #[global_allocator] | 73 | #[global_allocator] |
73 | static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; | 74 | static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; |
@@ -221,12 +222,12 @@ impl Analysis { | |||
221 | self.db.line_index(file_id) | 222 | self.db.line_index(file_id) |
222 | } | 223 | } |
223 | 224 | ||
224 | /// Selects the next syntactic nodes encopasing the range. | 225 | /// Selects the next syntactic nodes encompassing the range. |
225 | pub fn extend_selection(&self, frange: FileRange) -> Cancelable<TextRange> { | 226 | pub fn extend_selection(&self, frange: FileRange) -> Cancelable<TextRange> { |
226 | self.with_db(|db| extend_selection::extend_selection(db, frange)) | 227 | self.with_db(|db| extend_selection::extend_selection(db, frange)) |
227 | } | 228 | } |
228 | 229 | ||
229 | /// Returns position of the mathcing brace (all types of braces are | 230 | /// Returns position of the matching brace (all types of braces are |
230 | /// supported). | 231 | /// supported). |
231 | pub fn matching_brace(&self, position: FilePosition) -> Option<TextUnit> { | 232 | pub fn matching_brace(&self, position: FilePosition) -> Option<TextUnit> { |
232 | let file = self.db.parse(position.file_id); | 233 | let file = self.db.parse(position.file_id); |
@@ -316,7 +317,7 @@ impl Analysis { | |||
316 | self.with_db(|db| references::find_all_refs(db, position)) | 317 | self.with_db(|db| references::find_all_refs(db, position)) |
317 | } | 318 | } |
318 | 319 | ||
319 | /// Returns a short text descrbing element at position. | 320 | /// Returns a short text describing element at position. |
320 | pub fn hover(&self, position: FilePosition) -> Cancelable<Option<RangeInfo<String>>> { | 321 | pub fn hover(&self, position: FilePosition) -> Cancelable<Option<RangeInfo<String>>> { |
321 | self.with_db(|db| hover::hover(db, position)) | 322 | self.with_db(|db| hover::hover(db, position)) |
322 | } | 323 | } |
diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs index 8d8603062..550d69641 100644 --- a/crates/ra_ide_api/src/mock_analysis.rs +++ b/crates/ra_ide_api/src/mock_analysis.rs | |||
@@ -3,7 +3,7 @@ use std::sync::Arc; | |||
3 | use relative_path::RelativePathBuf; | 3 | use relative_path::RelativePathBuf; |
4 | use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; | 4 | use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; |
5 | 5 | ||
6 | use crate::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, FilePosition, FileRange, SourceRootId}; | 6 | use crate::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, FilePosition, FileRange, SourceRootId, Edition::Edition2018}; |
7 | 7 | ||
8 | /// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis | 8 | /// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis |
9 | /// from a set of in-memory files. | 9 | /// from a set of in-memory files. |
@@ -18,7 +18,7 @@ impl MockAnalysis { | |||
18 | } | 18 | } |
19 | /// Creates `MockAnalysis` using a fixture data in the following format: | 19 | /// Creates `MockAnalysis` using a fixture data in the following format: |
20 | /// | 20 | /// |
21 | /// ```notrust | 21 | /// ```rust,ignore |
22 | /// //- /main.rs | 22 | /// //- /main.rs |
23 | /// mod foo; | 23 | /// mod foo; |
24 | /// fn main() {} | 24 | /// fn main() {} |
@@ -89,9 +89,9 @@ impl MockAnalysis { | |||
89 | let path = RelativePathBuf::from_path(&path[1..]).unwrap(); | 89 | let path = RelativePathBuf::from_path(&path[1..]).unwrap(); |
90 | let file_id = FileId(i as u32 + 1); | 90 | let file_id = FileId(i as u32 + 1); |
91 | if path == "/lib.rs" || path == "/main.rs" { | 91 | if path == "/lib.rs" || path == "/main.rs" { |
92 | root_crate = Some(crate_graph.add_crate_root(file_id)); | 92 | root_crate = Some(crate_graph.add_crate_root(file_id, Edition2018)); |
93 | } else if path.ends_with("/lib.rs") { | 93 | } else if path.ends_with("/lib.rs") { |
94 | let other_crate = crate_graph.add_crate_root(file_id); | 94 | let other_crate = crate_graph.add_crate_root(file_id, Edition2018); |
95 | let crate_name = path.parent().unwrap().file_name().unwrap(); | 95 | let crate_name = path.parent().unwrap().file_name().unwrap(); |
96 | if let Some(root_crate) = root_crate { | 96 | if let Some(root_crate) = root_crate { |
97 | crate_graph.add_dep(root_crate, crate_name.into(), other_crate).unwrap(); | 97 | crate_graph.add_dep(root_crate, crate_name.into(), other_crate).unwrap(); |
diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index a2e4b6506..c559dca11 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs | |||
@@ -19,6 +19,7 @@ pub struct NavigationTarget { | |||
19 | kind: SyntaxKind, | 19 | kind: SyntaxKind, |
20 | full_range: TextRange, | 20 | full_range: TextRange, |
21 | focus_range: Option<TextRange>, | 21 | focus_range: Option<TextRange>, |
22 | container_name: Option<SmolStr>, | ||
22 | } | 23 | } |
23 | 24 | ||
24 | impl NavigationTarget { | 25 | impl NavigationTarget { |
@@ -26,6 +27,10 @@ impl NavigationTarget { | |||
26 | &self.name | 27 | &self.name |
27 | } | 28 | } |
28 | 29 | ||
30 | pub fn container_name(&self) -> Option<&SmolStr> { | ||
31 | self.container_name.as_ref() | ||
32 | } | ||
33 | |||
29 | pub fn kind(&self) -> SyntaxKind { | 34 | pub fn kind(&self) -> SyntaxKind { |
30 | self.kind | 35 | self.kind |
31 | } | 36 | } |
@@ -53,6 +58,7 @@ impl NavigationTarget { | |||
53 | kind: symbol.ptr.kind(), | 58 | kind: symbol.ptr.kind(), |
54 | full_range: symbol.ptr.range(), | 59 | full_range: symbol.ptr.range(), |
55 | focus_range: None, | 60 | focus_range: None, |
61 | container_name: symbol.container_name.clone(), | ||
56 | } | 62 | } |
57 | } | 63 | } |
58 | 64 | ||
@@ -67,6 +73,7 @@ impl NavigationTarget { | |||
67 | full_range: ptr.range(), | 73 | full_range: ptr.range(), |
68 | focus_range: None, | 74 | focus_range: None, |
69 | kind: NAME, | 75 | kind: NAME, |
76 | container_name: None, | ||
70 | } | 77 | } |
71 | } | 78 | } |
72 | 79 | ||
@@ -170,6 +177,9 @@ impl NavigationTarget { | |||
170 | if let Some(focus_range) = self.focus_range() { | 177 | if let Some(focus_range) = self.focus_range() { |
171 | buf.push_str(&format!(" {:?}", focus_range)) | 178 | buf.push_str(&format!(" {:?}", focus_range)) |
172 | } | 179 | } |
180 | if let Some(container_name) = self.container_name() { | ||
181 | buf.push_str(&format!(" {:?}", container_name)) | ||
182 | } | ||
173 | buf | 183 | buf |
174 | } | 184 | } |
175 | 185 | ||
@@ -192,6 +202,7 @@ impl NavigationTarget { | |||
192 | full_range: node.range(), | 202 | full_range: node.range(), |
193 | focus_range, | 203 | focus_range, |
194 | // ptr: Some(LocalSyntaxPtr::new(node)), | 204 | // ptr: Some(LocalSyntaxPtr::new(node)), |
205 | container_name: None, | ||
195 | } | 206 | } |
196 | } | 207 | } |
197 | } | 208 | } |
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index 2cb1cc9be..ca145f3e4 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs | |||
@@ -295,17 +295,17 @@ mod tests { | |||
295 | fn test_rename(text: &str, new_name: &str, expected: &str) { | 295 | fn test_rename(text: &str, new_name: &str, expected: &str) { |
296 | let (analysis, position) = single_file_with_position(text); | 296 | let (analysis, position) = single_file_with_position(text); |
297 | let source_change = analysis.rename(position, new_name).unwrap(); | 297 | let source_change = analysis.rename(position, new_name).unwrap(); |
298 | let mut text_edit_bulder = ra_text_edit::TextEditBuilder::default(); | 298 | let mut text_edit_builder = ra_text_edit::TextEditBuilder::default(); |
299 | let mut file_id: Option<FileId> = None; | 299 | let mut file_id: Option<FileId> = None; |
300 | if let Some(change) = source_change { | 300 | if let Some(change) = source_change { |
301 | for edit in change.source_file_edits { | 301 | for edit in change.source_file_edits { |
302 | file_id = Some(edit.file_id); | 302 | file_id = Some(edit.file_id); |
303 | for atom in edit.edit.as_atoms() { | 303 | for atom in edit.edit.as_atoms() { |
304 | text_edit_bulder.replace(atom.delete, atom.insert.clone()); | 304 | text_edit_builder.replace(atom.delete, atom.insert.clone()); |
305 | } | 305 | } |
306 | } | 306 | } |
307 | } | 307 | } |
308 | let result = text_edit_bulder.finish().apply(&*analysis.file_text(file_id.unwrap())); | 308 | let result = text_edit_builder.finish().apply(&*analysis.file_text(file_id.unwrap())); |
309 | assert_eq_text!(expected, &*result); | 309 | assert_eq_text!(expected, &*result); |
310 | } | 310 | } |
311 | } | 311 | } |
diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide_api/src/symbol_index.rs index de0f46134..afb10fa92 100644 --- a/crates/ra_ide_api/src/symbol_index.rs +++ b/crates/ra_ide_api/src/symbol_index.rs | |||
@@ -5,20 +5,20 @@ | |||
5 | //! symbols. The backbone of the index is the **awesome** `fst` crate by | 5 | //! symbols. The backbone of the index is the **awesome** `fst` crate by |
6 | //! @BurntSushi. | 6 | //! @BurntSushi. |
7 | //! | 7 | //! |
8 | //! In a nutshell, you give a set of strings to the `fst`, and it builds a | 8 | //! In a nutshell, you give a set of strings to `fst`, and it builds a |
9 | //! finite state machine describing this set of strings. The strings which | 9 | //! finite state machine describing this set of strings. The strings which |
10 | //! could fuzzy-match a pattern can also be described by a finite state machine. | 10 | //! could fuzzy-match a pattern can also be described by a finite state machine. |
11 | //! What is freakingly cool is that you can now traverse both state machines in | 11 | //! What is freaking cool is that you can now traverse both state machines in |
12 | //! lock-step to enumerate the strings which are both in the input set and | 12 | //! lock-step to enumerate the strings which are both in the input set and |
13 | //! fuzz-match the query. Or, more formally, given two languages described by | 13 | //! fuzz-match the query. Or, more formally, given two languages described by |
14 | //! fsts, one can build an product fst which describes the intersection of the | 14 | //! FSTs, one can build a product FST which describes the intersection of the |
15 | //! languages. | 15 | //! languages. |
16 | //! | 16 | //! |
17 | //! `fst` does not support cheap updating of the index, but it supports unioning | 17 | //! `fst` does not support cheap updating of the index, but it supports unioning |
18 | //! of state machines. So, to account for changing source code, we build an fst | 18 | //! of state machines. So, to account for changing source code, we build an FST |
19 | //! for each library (which is assumed to never change) and an fst for each rust | 19 | //! for each library (which is assumed to never change) and an FST for each Rust |
20 | //! file in the current workspace, and run a query against the union of all | 20 | //! file in the current workspace, and run a query against the union of all |
21 | //! those fsts. | 21 | //! those FSTs. |
22 | use std::{ | 22 | use std::{ |
23 | cmp::Ordering, | 23 | cmp::Ordering, |
24 | hash::{Hash, Hasher}, | 24 | hash::{Hash, Hasher}, |
@@ -32,6 +32,7 @@ use ra_syntax::{ | |||
32 | algo::{visit::{visitor, Visitor}, find_covering_node}, | 32 | algo::{visit::{visitor, Visitor}, find_covering_node}, |
33 | SyntaxKind::{self, *}, | 33 | SyntaxKind::{self, *}, |
34 | ast::{self, NameOwner}, | 34 | ast::{self, NameOwner}, |
35 | WalkEvent, | ||
35 | }; | 36 | }; |
36 | use ra_db::{ | 37 | use ra_db::{ |
37 | SourceRootId, SourceDatabase, | 38 | SourceRootId, SourceDatabase, |
@@ -62,17 +63,14 @@ pub(crate) trait SymbolsDatabase: hir::db::HirDatabase { | |||
62 | fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> { | 63 | fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> { |
63 | db.check_canceled(); | 64 | db.check_canceled(); |
64 | let source_file = db.parse(file_id); | 65 | let source_file = db.parse(file_id); |
65 | let mut symbols = source_file | 66 | |
66 | .syntax() | 67 | let mut symbols = source_file_to_file_symbols(&source_file, file_id); |
67 | .descendants() | ||
68 | .filter_map(to_symbol) | ||
69 | .map(move |(name, ptr)| FileSymbol { name, ptr, file_id }) | ||
70 | .collect::<Vec<_>>(); | ||
71 | 68 | ||
72 | for (name, text_range) in hir::source_binder::macro_symbols(db, file_id) { | 69 | for (name, text_range) in hir::source_binder::macro_symbols(db, file_id) { |
73 | let node = find_covering_node(source_file.syntax(), text_range); | 70 | let node = find_covering_node(source_file.syntax(), text_range); |
74 | let ptr = SyntaxNodePtr::new(node); | 71 | let ptr = SyntaxNodePtr::new(node); |
75 | symbols.push(FileSymbol { file_id, name, ptr }) | 72 | // TODO: Should we get container name for macro symbols? |
73 | symbols.push(FileSymbol { file_id, name, ptr, container_name: None }) | ||
76 | } | 74 | } |
77 | 75 | ||
78 | Arc::new(SymbolIndex::new(symbols)) | 76 | Arc::new(SymbolIndex::new(symbols)) |
@@ -158,13 +156,7 @@ impl SymbolIndex { | |||
158 | files: impl ParallelIterator<Item = (FileId, TreeArc<SourceFile>)>, | 156 | files: impl ParallelIterator<Item = (FileId, TreeArc<SourceFile>)>, |
159 | ) -> SymbolIndex { | 157 | ) -> SymbolIndex { |
160 | let symbols = files | 158 | let symbols = files |
161 | .flat_map(|(file_id, file)| { | 159 | .flat_map(|(file_id, file)| source_file_to_file_symbols(&file, file_id)) |
162 | file.syntax() | ||
163 | .descendants() | ||
164 | .filter_map(to_symbol) | ||
165 | .map(move |(name, ptr)| FileSymbol { name, ptr, file_id }) | ||
166 | .collect::<Vec<_>>() | ||
167 | }) | ||
168 | .collect::<Vec<_>>(); | 160 | .collect::<Vec<_>>(); |
169 | SymbolIndex::new(symbols) | 161 | SymbolIndex::new(symbols) |
170 | } | 162 | } |
@@ -215,12 +207,40 @@ pub(crate) struct FileSymbol { | |||
215 | pub(crate) file_id: FileId, | 207 | pub(crate) file_id: FileId, |
216 | pub(crate) name: SmolStr, | 208 | pub(crate) name: SmolStr, |
217 | pub(crate) ptr: SyntaxNodePtr, | 209 | pub(crate) ptr: SyntaxNodePtr, |
210 | pub(crate) container_name: Option<SmolStr>, | ||
211 | } | ||
212 | |||
213 | fn source_file_to_file_symbols(source_file: &SourceFile, file_id: FileId) -> Vec<FileSymbol> { | ||
214 | let mut symbols = Vec::new(); | ||
215 | let mut stack = Vec::new(); | ||
216 | |||
217 | for event in source_file.syntax().preorder() { | ||
218 | match event { | ||
219 | WalkEvent::Enter(node) => { | ||
220 | if let Some(mut symbol) = to_file_symbol(node, file_id) { | ||
221 | symbol.container_name = stack.last().cloned(); | ||
222 | |||
223 | stack.push(symbol.name.clone()); | ||
224 | symbols.push(symbol); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | WalkEvent::Leave(node) => { | ||
229 | if to_symbol(node).is_some() { | ||
230 | stack.pop(); | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | |||
236 | symbols | ||
218 | } | 237 | } |
219 | 238 | ||
220 | fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr)> { | 239 | fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr)> { |
221 | fn decl<N: NameOwner>(node: &N) -> Option<(SmolStr, SyntaxNodePtr)> { | 240 | fn decl<N: NameOwner>(node: &N) -> Option<(SmolStr, SyntaxNodePtr)> { |
222 | let name = node.name()?.text().clone(); | 241 | let name = node.name()?.text().clone(); |
223 | let ptr = SyntaxNodePtr::new(node.syntax()); | 242 | let ptr = SyntaxNodePtr::new(node.syntax()); |
243 | |||
224 | Some((name, ptr)) | 244 | Some((name, ptr)) |
225 | } | 245 | } |
226 | visitor() | 246 | visitor() |
@@ -234,3 +254,7 @@ fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr)> { | |||
234 | .visit(decl::<ast::StaticDef>) | 254 | .visit(decl::<ast::StaticDef>) |
235 | .accept(node)? | 255 | .accept(node)? |
236 | } | 256 | } |
257 | |||
258 | fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> { | ||
259 | to_symbol(node).map(move |(name, ptr)| FileSymbol { name, ptr, file_id, container_name: None }) | ||
260 | } | ||