diff options
Diffstat (limited to 'crates/ra_ide_api')
23 files changed, 295 insertions, 136 deletions
diff --git a/crates/ra_ide_api/Cargo.toml b/crates/ra_ide_api/Cargo.toml index 61942bbbb..79e473463 100644 --- a/crates/ra_ide_api/Cargo.toml +++ b/crates/ra_ide_api/Cargo.toml | |||
@@ -6,6 +6,7 @@ authors = ["Aleksey Kladov <[email protected]>"] | |||
6 | 6 | ||
7 | [dependencies] | 7 | [dependencies] |
8 | itertools = "0.8.0" | 8 | itertools = "0.8.0" |
9 | join_to_string = "0.1.3" | ||
9 | log = "0.4.5" | 10 | log = "0.4.5" |
10 | relative-path = "0.4.0" | 11 | relative-path = "0.4.0" |
11 | rayon = "1.0.2" | 12 | rayon = "1.0.2" |
@@ -13,7 +14,6 @@ fst = "0.3.1" | |||
13 | rustc-hash = "1.0" | 14 | rustc-hash = "1.0" |
14 | parking_lot = "0.7.0" | 15 | parking_lot = "0.7.0" |
15 | unicase = "2.2.0" | 16 | unicase = "2.2.0" |
16 | salsa = "0.10.0-alpha3" | ||
17 | 17 | ||
18 | ra_syntax = { path = "../ra_syntax" } | 18 | ra_syntax = { path = "../ra_syntax" } |
19 | ra_ide_api_light = { path = "../ra_ide_api_light" } | 19 | ra_ide_api_light = { path = "../ra_ide_api_light" } |
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs index 0449c1902..3267fff96 100644 --- a/crates/ra_ide_api/src/call_info.rs +++ b/crates/ra_ide_api/src/call_info.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use ra_db::SyntaxDatabase; | 1 | use ra_db::SourceDatabase; |
2 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | AstNode, SyntaxNode, TextUnit, TextRange, | 3 | AstNode, SyntaxNode, TextUnit, TextRange, |
4 | SyntaxKind::FN_DEF, | 4 | SyntaxKind::FN_DEF, |
@@ -10,7 +10,7 @@ use crate::{FilePosition, CallInfo, db::RootDatabase}; | |||
10 | 10 | ||
11 | /// Computes parameter information for the given call expression. | 11 | /// Computes parameter information for the given call expression. |
12 | pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> { | 12 | pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> { |
13 | let file = db.source_file(position.file_id); | 13 | let file = db.parse(position.file_id); |
14 | let syntax = file.syntax(); | 14 | let syntax = file.syntax(); |
15 | 15 | ||
16 | // Find the calling expression and it's NameRef | 16 | // Find the calling expression and it's NameRef |
@@ -22,7 +22,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
22 | let symbol = file_symbols | 22 | let symbol = file_symbols |
23 | .into_iter() | 23 | .into_iter() |
24 | .find(|it| it.ptr.kind() == FN_DEF)?; | 24 | .find(|it| it.ptr.kind() == FN_DEF)?; |
25 | let fn_file = db.source_file(symbol.file_id); | 25 | let fn_file = db.parse(symbol.file_id); |
26 | let fn_def = symbol.ptr.to_node(&fn_file); | 26 | let fn_def = symbol.ptr.to_node(&fn_file); |
27 | let fn_def = ast::FnDef::cast(fn_def).unwrap(); | 27 | let fn_def = ast::FnDef::cast(fn_def).unwrap(); |
28 | let mut call_info = CallInfo::new(fn_def)?; | 28 | let mut call_info = CallInfo::new(fn_def)?; |
diff --git a/crates/ra_ide_api/src/completion.rs b/crates/ra_ide_api/src/completion.rs index 565d57c37..b1867de42 100644 --- a/crates/ra_ide_api/src/completion.rs +++ b/crates/ra_ide_api/src/completion.rs | |||
@@ -9,7 +9,7 @@ mod complete_path; | |||
9 | mod complete_scope; | 9 | mod complete_scope; |
10 | mod complete_postfix; | 10 | mod complete_postfix; |
11 | 11 | ||
12 | use ra_db::SyntaxDatabase; | 12 | use ra_db::SourceDatabase; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | db, | 15 | db, |
@@ -45,7 +45,7 @@ pub use crate::completion::completion_item::{CompletionItem, CompletionItemKind, | |||
45 | /// identifier prefix/fuzzy match should be done higher in the stack, together | 45 | /// identifier prefix/fuzzy match should be done higher in the stack, together |
46 | /// with ordering of completions (currently this is done by the client). | 46 | /// with ordering of completions (currently this is done by the client). |
47 | pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Option<Completions> { | 47 | pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Option<Completions> { |
48 | let original_file = db.source_file(position.file_id); | 48 | let original_file = db.parse(position.file_id); |
49 | let ctx = CompletionContext::new(db, &original_file, position)?; | 49 | let ctx = CompletionContext::new(db, &original_file, position)?; |
50 | 50 | ||
51 | let mut acc = Completions::default(); | 51 | let mut acc = Completions::default(); |
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 060a46c5e..bad51cc51 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use hir::{Ty, AdtDef}; | 1 | use hir::{Ty, AdtDef, Docs}; |
2 | 2 | ||
3 | use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind}; | 3 | use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind}; |
4 | use crate::completion::completion_item::CompletionKind; | 4 | use crate::completion::completion_item::CompletionKind; |
@@ -38,6 +38,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) | |||
38 | ) | 38 | ) |
39 | .kind(CompletionItemKind::Field) | 39 | .kind(CompletionItemKind::Field) |
40 | .detail(field.ty(ctx.db).subst(substs).to_string()) | 40 | .detail(field.ty(ctx.db).subst(substs).to_string()) |
41 | .set_documentation(field.docs(ctx.db)) | ||
41 | .add_to(acc); | 42 | .add_to(acc); |
42 | } | 43 | } |
43 | } | 44 | } |
@@ -107,7 +108,10 @@ mod tests { | |||
107 | check_ref_completion( | 108 | check_ref_completion( |
108 | "struct_field_completion_self", | 109 | "struct_field_completion_self", |
109 | r" | 110 | r" |
110 | struct A { the_field: (u32,) } | 111 | struct A { |
112 | /// This is the_field | ||
113 | the_field: (u32,) | ||
114 | } | ||
111 | impl A { | 115 | impl A { |
112 | fn foo(self) { | 116 | fn foo(self) { |
113 | self.<|> | 117 | self.<|> |
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index e3f1d42f8..b33ddcde5 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | use join_to_string::join; | ||
2 | |||
1 | use crate::{ | 3 | use crate::{ |
2 | completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}, | 4 | completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}, |
3 | }; | 5 | }; |
@@ -29,6 +31,15 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
29 | hir::ModuleDef::Enum(e) => { | 31 | hir::ModuleDef::Enum(e) => { |
30 | e.variants(ctx.db).into_iter().for_each(|variant| { | 32 | e.variants(ctx.db).into_iter().for_each(|variant| { |
31 | if let Some(name) = variant.name(ctx.db) { | 33 | if let Some(name) = variant.name(ctx.db) { |
34 | let detail_types = variant | ||
35 | .fields(ctx.db) | ||
36 | .into_iter() | ||
37 | .map(|field| field.ty(ctx.db)); | ||
38 | let detail = join(detail_types) | ||
39 | .separator(", ") | ||
40 | .surround_with("(", ")") | ||
41 | .to_string(); | ||
42 | |||
32 | CompletionItem::new( | 43 | CompletionItem::new( |
33 | CompletionKind::Reference, | 44 | CompletionKind::Reference, |
34 | ctx.source_range(), | 45 | ctx.source_range(), |
@@ -36,6 +47,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
36 | ) | 47 | ) |
37 | .kind(CompletionItemKind::EnumVariant) | 48 | .kind(CompletionItemKind::EnumVariant) |
38 | .set_documentation(variant.docs(ctx.db)) | 49 | .set_documentation(variant.docs(ctx.db)) |
50 | .set_detail(Some(detail)) | ||
39 | .add_to(acc) | 51 | .add_to(acc) |
40 | } | 52 | } |
41 | }); | 53 | }); |
@@ -54,6 +66,22 @@ mod tests { | |||
54 | } | 66 | } |
55 | 67 | ||
56 | #[test] | 68 | #[test] |
69 | fn completes_mod_with_docs() { | ||
70 | check_reference_completion( | ||
71 | "mod_with_docs", | ||
72 | r" | ||
73 | use self::my<|>; | ||
74 | |||
75 | /// Some simple | ||
76 | /// docs describing `mod my`. | ||
77 | mod my { | ||
78 | struct Bar; | ||
79 | } | ||
80 | ", | ||
81 | ); | ||
82 | } | ||
83 | |||
84 | #[test] | ||
57 | fn completes_use_item_starting_with_self() { | 85 | fn completes_use_item_starting_with_self() { |
58 | check_reference_completion( | 86 | check_reference_completion( |
59 | "use_item_starting_with_self", | 87 | "use_item_starting_with_self", |
@@ -116,7 +144,7 @@ mod tests { | |||
116 | #[test] | 144 | #[test] |
117 | fn completes_enum_variant() { | 145 | fn completes_enum_variant() { |
118 | check_reference_completion( | 146 | check_reference_completion( |
119 | "reference_completion", | 147 | "enum_variant", |
120 | " | 148 | " |
121 | //- /lib.rs | 149 | //- /lib.rs |
122 | /// An enum | 150 | /// An enum |
@@ -130,4 +158,25 @@ mod tests { | |||
130 | ", | 158 | ", |
131 | ); | 159 | ); |
132 | } | 160 | } |
161 | |||
162 | #[test] | ||
163 | fn completes_enum_variant_with_details() { | ||
164 | check_reference_completion( | ||
165 | "enum_variant_with_details", | ||
166 | " | ||
167 | //- /lib.rs | ||
168 | struct S { field: u32 } | ||
169 | /// An enum | ||
170 | enum E { | ||
171 | /// Foo Variant (empty) | ||
172 | Foo, | ||
173 | /// Bar Variant with i32 and u32 | ||
174 | Bar(i32, u32), | ||
175 | /// | ||
176 | S(S), | ||
177 | } | ||
178 | fn foo() { let _ = E::<|> } | ||
179 | ", | ||
180 | ); | ||
181 | } | ||
133 | } | 182 | } |
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index b2b047766..b16ac2b28 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs | |||
@@ -215,7 +215,7 @@ impl Builder { | |||
215 | Some(it) => it, | 215 | Some(it) => it, |
216 | }; | 216 | }; |
217 | let (kind, docs) = match def { | 217 | let (kind, docs) = match def { |
218 | hir::ModuleDef::Module(_) => (CompletionItemKind::Module, None), | 218 | hir::ModuleDef::Module(it) => (CompletionItemKind::Module, it.docs(ctx.db)), |
219 | hir::ModuleDef::Function(func) => return self.from_function(ctx, func), | 219 | hir::ModuleDef::Function(func) => return self.from_function(ctx, func), |
220 | hir::ModuleDef::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), | 220 | hir::ModuleDef::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), |
221 | hir::ModuleDef::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), | 221 | hir::ModuleDef::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), |
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__reference_completion.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant.snap index e46f7807b..8c84439b2 100644 --- a/crates/ra_ide_api/src/completion/snapshots/completion_item__reference_completion.snap +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant.snap | |||
@@ -1,8 +1,8 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-23T23:49:43.278245900+00:00" | 2 | created: "2019-01-25T16:44:04.640545300+00:00" |
3 | creator: [email protected].1 | 3 | creator: [email protected].2 |
4 | expression: kind_completions | 4 | expression: kind_completions |
5 | source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs" | 5 | source: crates/ra_ide_api/src/completion/completion_item.rs |
6 | --- | 6 | --- |
7 | [ | 7 | [ |
8 | CompletionItem { | 8 | CompletionItem { |
@@ -11,7 +11,9 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs" | |||
11 | kind: Some( | 11 | kind: Some( |
12 | EnumVariant | 12 | EnumVariant |
13 | ), | 13 | ), |
14 | detail: None, | 14 | detail: Some( |
15 | "()" | ||
16 | ), | ||
15 | documentation: Some( | 17 | documentation: Some( |
16 | Documentation( | 18 | Documentation( |
17 | "Foo Variant" | 19 | "Foo Variant" |
@@ -29,7 +31,9 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs" | |||
29 | kind: Some( | 31 | kind: Some( |
30 | EnumVariant | 32 | EnumVariant |
31 | ), | 33 | ), |
32 | detail: None, | 34 | detail: Some( |
35 | "(i32)" | ||
36 | ), | ||
33 | documentation: Some( | 37 | documentation: Some( |
34 | Documentation( | 38 | Documentation( |
35 | "Bar Variant with i32" | 39 | "Bar Variant with i32" |
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant_with_details.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant_with_details.snap new file mode 100644 index 000000000..384634517 --- /dev/null +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant_with_details.snap | |||
@@ -0,0 +1,64 @@ | |||
1 | --- | ||
2 | created: "2019-01-25T16:44:04.641542400+00:00" | ||
3 | creator: [email protected] | ||
4 | expression: kind_completions | ||
5 | source: crates/ra_ide_api/src/completion/completion_item.rs | ||
6 | --- | ||
7 | [ | ||
8 | CompletionItem { | ||
9 | completion_kind: Reference, | ||
10 | label: "Foo", | ||
11 | kind: Some( | ||
12 | EnumVariant | ||
13 | ), | ||
14 | detail: Some( | ||
15 | "()" | ||
16 | ), | ||
17 | documentation: Some( | ||
18 | Documentation( | ||
19 | "Foo Variant (empty)" | ||
20 | ) | ||
21 | ), | ||
22 | lookup: None, | ||
23 | insert_text: None, | ||
24 | insert_text_format: PlainText, | ||
25 | source_range: [180; 180), | ||
26 | text_edit: None | ||
27 | }, | ||
28 | CompletionItem { | ||
29 | completion_kind: Reference, | ||
30 | label: "Bar", | ||
31 | kind: Some( | ||
32 | EnumVariant | ||
33 | ), | ||
34 | detail: Some( | ||
35 | "(i32, u32)" | ||
36 | ), | ||
37 | documentation: Some( | ||
38 | Documentation( | ||
39 | "Bar Variant with i32 and u32" | ||
40 | ) | ||
41 | ), | ||
42 | lookup: None, | ||
43 | insert_text: None, | ||
44 | insert_text_format: PlainText, | ||
45 | source_range: [180; 180), | ||
46 | text_edit: None | ||
47 | }, | ||
48 | CompletionItem { | ||
49 | completion_kind: Reference, | ||
50 | label: "S", | ||
51 | kind: Some( | ||
52 | EnumVariant | ||
53 | ), | ||
54 | detail: Some( | ||
55 | "(S)" | ||
56 | ), | ||
57 | documentation: None, | ||
58 | lookup: None, | ||
59 | insert_text: None, | ||
60 | insert_text_format: PlainText, | ||
61 | source_range: [180; 180), | ||
62 | text_edit: None | ||
63 | } | ||
64 | ] | ||
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__mod_with_docs.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__mod_with_docs.snap new file mode 100644 index 000000000..3db7119a7 --- /dev/null +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__mod_with_docs.snap | |||
@@ -0,0 +1,26 @@ | |||
1 | --- | ||
2 | created: "2019-01-25T17:49:28.949186500+00:00" | ||
3 | creator: [email protected] | ||
4 | expression: kind_completions | ||
5 | source: crates/ra_ide_api/src/completion/completion_item.rs | ||
6 | --- | ||
7 | [ | ||
8 | CompletionItem { | ||
9 | completion_kind: Reference, | ||
10 | label: "my", | ||
11 | kind: Some( | ||
12 | Module | ||
13 | ), | ||
14 | detail: None, | ||
15 | documentation: Some( | ||
16 | Documentation( | ||
17 | "Some simple\ndocs describing `mod my`." | ||
18 | ) | ||
19 | ), | ||
20 | lookup: None, | ||
21 | insert_text: None, | ||
22 | insert_text_format: PlainText, | ||
23 | source_range: [23; 25), | ||
24 | text_edit: None | ||
25 | } | ||
26 | ] | ||
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap index 80e8f3df5..580e92a90 100644 --- a/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap | |||
@@ -1,5 +1,5 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-23T13:19:23.501297515+00:00" | 2 | created: "2019-01-25T19:27:09.519688600+00:00" |
3 | creator: [email protected] | 3 | creator: [email protected] |
4 | expression: kind_completions | 4 | expression: kind_completions |
5 | source: crates/ra_ide_api/src/completion/completion_item.rs | 5 | source: crates/ra_ide_api/src/completion/completion_item.rs |
@@ -14,11 +14,15 @@ source: crates/ra_ide_api/src/completion/completion_item.rs | |||
14 | detail: Some( | 14 | detail: Some( |
15 | "(u32,)" | 15 | "(u32,)" |
16 | ), | 16 | ), |
17 | documentation: None, | 17 | documentation: Some( |
18 | Documentation( | ||
19 | "This is the_field" | ||
20 | ) | ||
21 | ), | ||
18 | lookup: None, | 22 | lookup: None, |
19 | insert_text: None, | 23 | insert_text: None, |
20 | insert_text_format: PlainText, | 24 | insert_text_format: PlainText, |
21 | source_range: [121; 121), | 25 | source_range: [187; 187), |
22 | text_edit: None | 26 | text_edit: None |
23 | }, | 27 | }, |
24 | CompletionItem { | 28 | CompletionItem { |
@@ -36,7 +40,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs | |||
36 | "foo()$0" | 40 | "foo()$0" |
37 | ), | 41 | ), |
38 | insert_text_format: Snippet, | 42 | insert_text_format: Snippet, |
39 | source_range: [121; 121), | 43 | source_range: [187; 187), |
40 | text_edit: None | 44 | text_edit: None |
41 | } | 45 | } |
42 | ] | 46 | ] |
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs index f0190ae51..3da93ec35 100644 --- a/crates/ra_ide_api/src/db.rs +++ b/crates/ra_ide_api/src/db.rs | |||
@@ -1,18 +1,17 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_db::{ | 3 | use ra_db::{ |
4 | BaseDatabase, FileId, Canceled, | 4 | CheckCanceled, FileId, Canceled, SourceDatabase, |
5 | salsa::{self, Database}, | 5 | salsa, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | use crate::{symbol_index, LineIndex}; | 8 | use crate::{LineIndex, symbol_index::{self, SymbolsDatabase}}; |
9 | 9 | ||
10 | #[salsa::database( | 10 | #[salsa::database( |
11 | ra_db::FilesDatabase, | 11 | ra_db::SourceDatabaseStorage, |
12 | ra_db::SyntaxDatabase, | 12 | LineIndexDatabaseStorage, |
13 | LineIndexDatabase, | 13 | symbol_index::SymbolsDatabaseStorage, |
14 | symbol_index::SymbolsDatabase, | 14 | hir::db::HirDatabaseStorage |
15 | hir::db::HirDatabase | ||
16 | )] | 15 | )] |
17 | #[derive(Debug)] | 16 | #[derive(Debug)] |
18 | pub(crate) struct RootDatabase { | 17 | pub(crate) struct RootDatabase { |
@@ -35,12 +34,9 @@ impl Default for RootDatabase { | |||
35 | runtime: salsa::Runtime::default(), | 34 | runtime: salsa::Runtime::default(), |
36 | interner: Default::default(), | 35 | interner: Default::default(), |
37 | }; | 36 | }; |
38 | db.query_mut(ra_db::CrateGraphQuery) | 37 | db.set_crate_graph(Default::default()); |
39 | .set((), Default::default()); | 38 | db.set_local_roots(Default::default()); |
40 | db.query_mut(ra_db::LocalRootsQuery) | 39 | db.set_library_roots(Default::default()); |
41 | .set((), Default::default()); | ||
42 | db.query_mut(ra_db::LibraryRootsQuery) | ||
43 | .set((), Default::default()); | ||
44 | db | 40 | db |
45 | } | 41 | } |
46 | } | 42 | } |
@@ -54,7 +50,7 @@ impl salsa::ParallelDatabase for RootDatabase { | |||
54 | } | 50 | } |
55 | } | 51 | } |
56 | 52 | ||
57 | impl BaseDatabase for RootDatabase {} | 53 | impl CheckCanceled for RootDatabase {} |
58 | 54 | ||
59 | impl AsRef<hir::HirInterner> for RootDatabase { | 55 | impl AsRef<hir::HirInterner> for RootDatabase { |
60 | fn as_ref(&self) -> &hir::HirInterner { | 56 | fn as_ref(&self) -> &hir::HirInterner { |
@@ -62,12 +58,12 @@ impl AsRef<hir::HirInterner> for RootDatabase { | |||
62 | } | 58 | } |
63 | } | 59 | } |
64 | 60 | ||
65 | #[salsa::query_group] | 61 | #[salsa::query_group(LineIndexDatabaseStorage)] |
66 | pub(crate) trait LineIndexDatabase: ra_db::FilesDatabase + BaseDatabase { | 62 | pub(crate) trait LineIndexDatabase: ra_db::SourceDatabase + CheckCanceled { |
67 | fn line_index(&self, file_id: FileId) -> Arc<LineIndex>; | 63 | fn line_index(&self, file_id: FileId) -> Arc<LineIndex>; |
68 | } | 64 | } |
69 | 65 | ||
70 | fn line_index(db: &impl ra_db::FilesDatabase, file_id: FileId) -> Arc<LineIndex> { | 66 | fn line_index(db: &impl ra_db::SourceDatabase, file_id: FileId) -> Arc<LineIndex> { |
71 | let text = db.file_text(file_id); | 67 | let text = db.file_text(file_id); |
72 | Arc::new(LineIndex::new(&*text)) | 68 | Arc::new(LineIndex::new(&*text)) |
73 | } | 69 | } |
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs index 718b4def5..cd2ebe471 100644 --- a/crates/ra_ide_api/src/extend_selection.rs +++ b/crates/ra_ide_api/src/extend_selection.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use ra_db::SyntaxDatabase; | 1 | use ra_db::SourceDatabase; |
2 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | SyntaxNode, AstNode, SourceFile, | 3 | SyntaxNode, AstNode, SourceFile, |
4 | ast, algo::find_covering_node, | 4 | ast, algo::find_covering_node, |
@@ -10,7 +10,7 @@ use crate::{ | |||
10 | }; | 10 | }; |
11 | 11 | ||
12 | pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRange { | 12 | pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRange { |
13 | let source_file = db.source_file(frange.file_id); | 13 | let source_file = db.parse(frange.file_id); |
14 | if let Some(range) = extend_selection_in_macro(db, &source_file, frange) { | 14 | if let Some(range) = extend_selection_in_macro(db, &source_file, frange) { |
15 | return range; | 15 | return range; |
16 | } | 16 | } |
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 46bdde00d..2a20c20ee 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -1,8 +1,9 @@ | |||
1 | use ra_db::{FileId, SyntaxDatabase}; | 1 | use ra_db::{FileId, SourceDatabase}; |
2 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | AstNode, ast, | 3 | AstNode, ast, |
4 | algo::find_node_at_offset, | 4 | algo::find_node_at_offset, |
5 | }; | 5 | }; |
6 | use test_utils::tested_by; | ||
6 | 7 | ||
7 | use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; | 8 | use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; |
8 | 9 | ||
@@ -10,7 +11,7 @@ pub(crate) fn goto_definition( | |||
10 | db: &RootDatabase, | 11 | db: &RootDatabase, |
11 | position: FilePosition, | 12 | position: FilePosition, |
12 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { | 13 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { |
13 | let file = db.source_file(position.file_id); | 14 | let file = db.parse(position.file_id); |
14 | let syntax = file.syntax(); | 15 | let syntax = file.syntax(); |
15 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { | 16 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { |
16 | let navs = reference_definition(db, position.file_id, name_ref).to_vec(); | 17 | let navs = reference_definition(db, position.file_id, name_ref).to_vec(); |
@@ -60,6 +61,7 @@ pub(crate) fn reference_definition( | |||
60 | .parent() | 61 | .parent() |
61 | .and_then(ast::MethodCallExpr::cast) | 62 | .and_then(ast::MethodCallExpr::cast) |
62 | { | 63 | { |
64 | tested_by!(goto_definition_works_for_methods); | ||
63 | let infer_result = function.infer(db); | 65 | let infer_result = function.infer(db); |
64 | let syntax_mapping = function.body_syntax_mapping(db); | 66 | let syntax_mapping = function.body_syntax_mapping(db); |
65 | let expr = ast::Expr::cast(method_call.syntax()).unwrap(); | 67 | let expr = ast::Expr::cast(method_call.syntax()).unwrap(); |
@@ -70,6 +72,19 @@ pub(crate) fn reference_definition( | |||
70 | return Exact(NavigationTarget::from_function(db, func)); | 72 | return Exact(NavigationTarget::from_function(db, func)); |
71 | }; | 73 | }; |
72 | } | 74 | } |
75 | // It could also be a field access | ||
76 | if let Some(field_expr) = name_ref.syntax().parent().and_then(ast::FieldExpr::cast) { | ||
77 | tested_by!(goto_definition_works_for_fields); | ||
78 | let infer_result = function.infer(db); | ||
79 | let syntax_mapping = function.body_syntax_mapping(db); | ||
80 | let expr = ast::Expr::cast(field_expr.syntax()).unwrap(); | ||
81 | if let Some(field) = syntax_mapping | ||
82 | .node_expr(expr) | ||
83 | .and_then(|it| infer_result.field_resolution(it)) | ||
84 | { | ||
85 | return Exact(NavigationTarget::from_field(db, field)); | ||
86 | }; | ||
87 | } | ||
73 | } | 88 | } |
74 | // Then try module name resolution | 89 | // Then try module name resolution |
75 | if let Some(module) = hir::source_binder::module_from_child_node(db, file_id, name_ref.syntax()) | 90 | if let Some(module) = hir::source_binder::module_from_child_node(db, file_id, name_ref.syntax()) |
@@ -82,9 +97,7 @@ pub(crate) fn reference_definition( | |||
82 | { | 97 | { |
83 | let resolved = module.resolve_path(db, &path); | 98 | let resolved = module.resolve_path(db, &path); |
84 | if let Some(def_id) = resolved.take_types().or(resolved.take_values()) { | 99 | if let Some(def_id) = resolved.take_types().or(resolved.take_values()) { |
85 | if let Some(target) = NavigationTarget::from_def(db, def_id) { | 100 | return Exact(NavigationTarget::from_def(db, def_id)); |
86 | return Exact(target); | ||
87 | } | ||
88 | } | 101 | } |
89 | } | 102 | } |
90 | } | 103 | } |
@@ -117,6 +130,8 @@ fn name_definition( | |||
117 | 130 | ||
118 | #[cfg(test)] | 131 | #[cfg(test)] |
119 | mod tests { | 132 | mod tests { |
133 | use test_utils::covers; | ||
134 | |||
120 | use crate::mock_analysis::analysis_and_position; | 135 | use crate::mock_analysis::analysis_and_position; |
121 | 136 | ||
122 | fn check_goto(fixuture: &str, expected: &str) { | 137 | fn check_goto(fixuture: &str, expected: &str) { |
@@ -183,6 +198,7 @@ mod tests { | |||
183 | 198 | ||
184 | #[test] | 199 | #[test] |
185 | fn goto_definition_works_for_methods() { | 200 | fn goto_definition_works_for_methods() { |
201 | covers!(goto_definition_works_for_methods); | ||
186 | check_goto( | 202 | check_goto( |
187 | " | 203 | " |
188 | //- /lib.rs | 204 | //- /lib.rs |
@@ -197,15 +213,23 @@ mod tests { | |||
197 | ", | 213 | ", |
198 | "frobnicate FN_DEF FileId(1) [27; 52) [30; 40)", | 214 | "frobnicate FN_DEF FileId(1) [27; 52) [30; 40)", |
199 | ); | 215 | ); |
216 | } | ||
200 | 217 | ||
218 | #[test] | ||
219 | fn goto_definition_works_for_fields() { | ||
220 | covers!(goto_definition_works_for_fields); | ||
201 | check_goto( | 221 | check_goto( |
202 | " | 222 | " |
203 | //- /lib.rs | 223 | //- /lib.rs |
204 | mod <|>foo; | 224 | struct Foo { |
205 | //- /foo/mod.rs | 225 | spam: u32, |
206 | // empty | 226 | } |
227 | |||
228 | fn bar(foo: &Foo) { | ||
229 | foo.spam<|>; | ||
230 | } | ||
207 | ", | 231 | ", |
208 | "foo SOURCE_FILE FileId(2) [0; 10)", | 232 | "spam NAMED_FIELD_DEF FileId(1) [17; 26) [17; 21)", |
209 | ); | 233 | ); |
210 | } | 234 | } |
211 | } | 235 | } |
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 4d4bfbc4d..ff9ae2d9c 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use ra_db::{SyntaxDatabase}; | 1 | use ra_db::SourceDatabase; |
2 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | AstNode, SyntaxNode, TreeArc, ast, | 3 | AstNode, SyntaxNode, TreeArc, ast, |
4 | algo::{find_covering_node, find_node_at_offset, find_leaf_at_offset, visit::{visitor, Visitor}}, | 4 | algo::{find_covering_node, find_node_at_offset, find_leaf_at_offset, visit::{visitor, Visitor}}, |
@@ -7,7 +7,7 @@ use ra_syntax::{ | |||
7 | use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, NavigationTarget}; | 7 | use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, NavigationTarget}; |
8 | 8 | ||
9 | pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeInfo<String>> { | 9 | pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeInfo<String>> { |
10 | let file = db.source_file(position.file_id); | 10 | let file = db.parse(position.file_id); |
11 | let mut res = Vec::new(); | 11 | let mut res = Vec::new(); |
12 | 12 | ||
13 | let mut range = None; | 13 | let mut range = None; |
@@ -53,7 +53,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
53 | } | 53 | } |
54 | 54 | ||
55 | pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> { | 55 | pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> { |
56 | let file = db.source_file(frange.file_id); | 56 | let file = db.parse(frange.file_id); |
57 | let syntax = file.syntax(); | 57 | let syntax = file.syntax(); |
58 | let leaf_node = find_covering_node(syntax, frange.range); | 58 | let leaf_node = find_covering_node(syntax, frange.range); |
59 | // if we picked identifier, expand to pattern/expression | 59 | // if we picked identifier, expand to pattern/expression |
@@ -88,7 +88,7 @@ fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Option<String> { | |||
88 | 88 | ||
89 | impl NavigationTarget { | 89 | impl NavigationTarget { |
90 | fn node(&self, db: &RootDatabase) -> Option<TreeArc<SyntaxNode>> { | 90 | fn node(&self, db: &RootDatabase) -> Option<TreeArc<SyntaxNode>> { |
91 | let source_file = db.source_file(self.file_id()); | 91 | let source_file = db.parse(self.file_id()); |
92 | let source_file = source_file.syntax(); | 92 | let source_file = source_file.syntax(); |
93 | let node = source_file | 93 | let node = source_file |
94 | .descendants() | 94 | .descendants() |
diff --git a/crates/ra_ide_api/src/imp.rs b/crates/ra_ide_api/src/imp.rs index 961f7b230..399433a01 100644 --- a/crates/ra_ide_api/src/imp.rs +++ b/crates/ra_ide_api/src/imp.rs | |||
@@ -4,8 +4,8 @@ use hir::{ | |||
4 | self, Problem, source_binder | 4 | self, Problem, source_binder |
5 | }; | 5 | }; |
6 | use ra_db::{ | 6 | use ra_db::{ |
7 | FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase, | 7 | SourceDatabase, SourceRoot, SourceRootId, |
8 | salsa::Database, | 8 | salsa::{Database, SweepStrategy}, |
9 | }; | 9 | }; |
10 | use ra_ide_api_light::{self, assists, LocalEdit, Severity}; | 10 | use ra_ide_api_light::{self, assists, LocalEdit, Severity}; |
11 | use ra_syntax::{ | 11 | use ra_syntax::{ |
@@ -76,14 +76,14 @@ impl db::RootDatabase { | |||
76 | /// syntax trees. However, if we actually do that, everything is recomputed | 76 | /// syntax trees. However, if we actually do that, everything is recomputed |
77 | /// for some reason. Needs investigation. | 77 | /// for some reason. Needs investigation. |
78 | pub(crate) fn collect_garbage(&mut self) { | 78 | pub(crate) fn collect_garbage(&mut self) { |
79 | self.query(ra_db::SourceFileQuery) | 79 | self.query(ra_db::ParseQuery) |
80 | .sweep(salsa::SweepStrategy::default().discard_values()); | 80 | .sweep(SweepStrategy::default().discard_values()); |
81 | self.query(hir::db::HirSourceFileQuery) | 81 | self.query(hir::db::HirParseQuery) |
82 | .sweep(salsa::SweepStrategy::default().discard_values()); | 82 | .sweep(SweepStrategy::default().discard_values()); |
83 | self.query(hir::db::FileItemsQuery) | 83 | self.query(hir::db::FileItemsQuery) |
84 | .sweep(salsa::SweepStrategy::default().discard_values()); | 84 | .sweep(SweepStrategy::default().discard_values()); |
85 | self.query(hir::db::FileItemQuery) | 85 | self.query(hir::db::FileItemQuery) |
86 | .sweep(salsa::SweepStrategy::default().discard_values()); | 86 | .sweep(SweepStrategy::default().discard_values()); |
87 | } | 87 | } |
88 | } | 88 | } |
89 | 89 | ||
@@ -102,7 +102,7 @@ impl db::RootDatabase { | |||
102 | } | 102 | } |
103 | 103 | ||
104 | pub(crate) fn find_all_refs(&self, position: FilePosition) -> Vec<(FileId, TextRange)> { | 104 | pub(crate) fn find_all_refs(&self, position: FilePosition) -> Vec<(FileId, TextRange)> { |
105 | let file = self.source_file(position.file_id); | 105 | let file = self.parse(position.file_id); |
106 | // Find the binding associated with the offset | 106 | // Find the binding associated with the offset |
107 | let (binding, descr) = match find_binding(self, &file, position) { | 107 | let (binding, descr) = match find_binding(self, &file, position) { |
108 | None => return Vec::new(), | 108 | None => return Vec::new(), |
@@ -150,7 +150,7 @@ impl db::RootDatabase { | |||
150 | } | 150 | } |
151 | 151 | ||
152 | pub(crate) fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> { | 152 | pub(crate) fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> { |
153 | let syntax = self.source_file(file_id); | 153 | let syntax = self.parse(file_id); |
154 | 154 | ||
155 | let mut res = ra_ide_api_light::diagnostics(&syntax) | 155 | let mut res = ra_ide_api_light::diagnostics(&syntax) |
156 | .into_iter() | 156 | .into_iter() |
@@ -214,7 +214,7 @@ impl db::RootDatabase { | |||
214 | } | 214 | } |
215 | 215 | ||
216 | pub(crate) fn assists(&self, frange: FileRange) -> Vec<SourceChange> { | 216 | pub(crate) fn assists(&self, frange: FileRange) -> Vec<SourceChange> { |
217 | let file = self.source_file(frange.file_id); | 217 | let file = self.parse(frange.file_id); |
218 | assists::assists(&file, frange.range) | 218 | assists::assists(&file, frange.range) |
219 | .into_iter() | 219 | .into_iter() |
220 | .map(|local_edit| SourceChange::from_local_edit(frange.file_id, local_edit)) | 220 | .map(|local_edit| SourceChange::from_local_edit(frange.file_id, local_edit)) |
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index ffd026b04..43c8bea71 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs | |||
@@ -34,7 +34,7 @@ use std::{fmt, sync::Arc}; | |||
34 | use ra_syntax::{SourceFile, TreeArc, TextRange, TextUnit}; | 34 | use ra_syntax::{SourceFile, TreeArc, TextRange, TextUnit}; |
35 | use ra_text_edit::TextEdit; | 35 | use ra_text_edit::TextEdit; |
36 | use ra_db::{ | 36 | use ra_db::{ |
37 | SyntaxDatabase, FilesDatabase, BaseDatabase, | 37 | SourceDatabase, CheckCanceled, |
38 | salsa::{self, ParallelDatabase}, | 38 | salsa::{self, ParallelDatabase}, |
39 | }; | 39 | }; |
40 | use rayon::prelude::*; | 40 | use rayon::prelude::*; |
@@ -313,7 +313,7 @@ impl Analysis { | |||
313 | 313 | ||
314 | /// Gets the syntax tree of the file. | 314 | /// Gets the syntax tree of the file. |
315 | pub fn parse(&self, file_id: FileId) -> TreeArc<SourceFile> { | 315 | pub fn parse(&self, file_id: FileId) -> TreeArc<SourceFile> { |
316 | self.db.source_file(file_id).clone() | 316 | self.db.parse(file_id).clone() |
317 | } | 317 | } |
318 | 318 | ||
319 | /// Gets the file's `LineIndex`: data structure to convert between absolute | 319 | /// Gets the file's `LineIndex`: data structure to convert between absolute |
@@ -330,21 +330,21 @@ impl Analysis { | |||
330 | /// Returns position of the mathcing brace (all types of braces are | 330 | /// Returns position of the mathcing brace (all types of braces are |
331 | /// supported). | 331 | /// supported). |
332 | pub fn matching_brace(&self, position: FilePosition) -> Option<TextUnit> { | 332 | pub fn matching_brace(&self, position: FilePosition) -> Option<TextUnit> { |
333 | let file = self.db.source_file(position.file_id); | 333 | let file = self.db.parse(position.file_id); |
334 | ra_ide_api_light::matching_brace(&file, position.offset) | 334 | ra_ide_api_light::matching_brace(&file, position.offset) |
335 | } | 335 | } |
336 | 336 | ||
337 | /// Returns a syntax tree represented as `String`, for debug purposes. | 337 | /// Returns a syntax tree represented as `String`, for debug purposes. |
338 | // FIXME: use a better name here. | 338 | // FIXME: use a better name here. |
339 | pub fn syntax_tree(&self, file_id: FileId) -> String { | 339 | pub fn syntax_tree(&self, file_id: FileId) -> String { |
340 | let file = self.db.source_file(file_id); | 340 | let file = self.db.parse(file_id); |
341 | ra_ide_api_light::syntax_tree(&file) | 341 | ra_ide_api_light::syntax_tree(&file) |
342 | } | 342 | } |
343 | 343 | ||
344 | /// Returns an edit to remove all newlines in the range, cleaning up minor | 344 | /// Returns an edit to remove all newlines in the range, cleaning up minor |
345 | /// stuff like trailing commas. | 345 | /// stuff like trailing commas. |
346 | pub fn join_lines(&self, frange: FileRange) -> SourceChange { | 346 | pub fn join_lines(&self, frange: FileRange) -> SourceChange { |
347 | let file = self.db.source_file(frange.file_id); | 347 | let file = self.db.parse(frange.file_id); |
348 | SourceChange::from_local_edit( | 348 | SourceChange::from_local_edit( |
349 | frange.file_id, | 349 | frange.file_id, |
350 | ra_ide_api_light::join_lines(&file, frange.range), | 350 | ra_ide_api_light::join_lines(&file, frange.range), |
@@ -354,7 +354,7 @@ impl Analysis { | |||
354 | /// Returns an edit which should be applied when opening a new line, fixing | 354 | /// Returns an edit which should be applied when opening a new line, fixing |
355 | /// up minor stuff like continuing the comment. | 355 | /// up minor stuff like continuing the comment. |
356 | pub fn on_enter(&self, position: FilePosition) -> Option<SourceChange> { | 356 | pub fn on_enter(&self, position: FilePosition) -> Option<SourceChange> { |
357 | let file = self.db.source_file(position.file_id); | 357 | let file = self.db.parse(position.file_id); |
358 | let edit = ra_ide_api_light::on_enter(&file, position.offset)?; | 358 | let edit = ra_ide_api_light::on_enter(&file, position.offset)?; |
359 | Some(SourceChange::from_local_edit(position.file_id, edit)) | 359 | Some(SourceChange::from_local_edit(position.file_id, edit)) |
360 | } | 360 | } |
@@ -363,14 +363,14 @@ impl Analysis { | |||
363 | /// this works when adding `let =`. | 363 | /// this works when adding `let =`. |
364 | // FIXME: use a snippet completion instead of this hack here. | 364 | // FIXME: use a snippet completion instead of this hack here. |
365 | pub fn on_eq_typed(&self, position: FilePosition) -> Option<SourceChange> { | 365 | pub fn on_eq_typed(&self, position: FilePosition) -> Option<SourceChange> { |
366 | let file = self.db.source_file(position.file_id); | 366 | let file = self.db.parse(position.file_id); |
367 | let edit = ra_ide_api_light::on_eq_typed(&file, position.offset)?; | 367 | let edit = ra_ide_api_light::on_eq_typed(&file, position.offset)?; |
368 | Some(SourceChange::from_local_edit(position.file_id, edit)) | 368 | Some(SourceChange::from_local_edit(position.file_id, edit)) |
369 | } | 369 | } |
370 | 370 | ||
371 | /// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately. | 371 | /// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately. |
372 | pub fn on_dot_typed(&self, position: FilePosition) -> Option<SourceChange> { | 372 | pub fn on_dot_typed(&self, position: FilePosition) -> Option<SourceChange> { |
373 | let file = self.db.source_file(position.file_id); | 373 | let file = self.db.parse(position.file_id); |
374 | let edit = ra_ide_api_light::on_dot_typed(&file, position.offset)?; | 374 | let edit = ra_ide_api_light::on_dot_typed(&file, position.offset)?; |
375 | Some(SourceChange::from_local_edit(position.file_id, edit)) | 375 | Some(SourceChange::from_local_edit(position.file_id, edit)) |
376 | } | 376 | } |
@@ -378,13 +378,13 @@ impl Analysis { | |||
378 | /// Returns a tree representation of symbols in the file. Useful to draw a | 378 | /// Returns a tree representation of symbols in the file. Useful to draw a |
379 | /// file outline. | 379 | /// file outline. |
380 | pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> { | 380 | pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> { |
381 | let file = self.db.source_file(file_id); | 381 | let file = self.db.parse(file_id); |
382 | ra_ide_api_light::file_structure(&file) | 382 | ra_ide_api_light::file_structure(&file) |
383 | } | 383 | } |
384 | 384 | ||
385 | /// Returns the set of folding ranges. | 385 | /// Returns the set of folding ranges. |
386 | pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> { | 386 | pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> { |
387 | let file = self.db.source_file(file_id); | 387 | let file = self.db.parse(file_id); |
388 | ra_ide_api_light::folding_ranges(&file) | 388 | ra_ide_api_light::folding_ranges(&file) |
389 | } | 389 | } |
390 | 390 | ||
diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide_api/src/marks.rs index dc5b2702a..e33bf6c91 100644 --- a/crates/ra_ide_api/src/marks.rs +++ b/crates/ra_ide_api/src/marks.rs | |||
@@ -1 +1,5 @@ | |||
1 | test_utils::marks!(inserts_parens_for_function_calls); | 1 | test_utils::marks!( |
2 | inserts_parens_for_function_calls | ||
3 | goto_definition_works_for_methods | ||
4 | goto_definition_works_for_fields | ||
5 | ); | ||
diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index c5be8e01b..d73d4afa7 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs | |||
@@ -3,7 +3,7 @@ use ra_syntax::{ | |||
3 | SyntaxNode, AstNode, SmolStr, TextRange, ast, | 3 | SyntaxNode, AstNode, SmolStr, TextRange, ast, |
4 | SyntaxKind::{self, NAME}, | 4 | SyntaxKind::{self, NAME}, |
5 | }; | 5 | }; |
6 | use hir::{ModuleSource}; | 6 | use hir::{ModuleSource, FieldSource}; |
7 | 7 | ||
8 | use crate::{FileSymbol, db::RootDatabase}; | 8 | use crate::{FileSymbol, db::RootDatabase}; |
9 | 9 | ||
@@ -101,62 +101,48 @@ impl NavigationTarget { | |||
101 | NavigationTarget::from_named(file_id.original_file(db), &*fn_def) | 101 | NavigationTarget::from_named(file_id.original_file(db), &*fn_def) |
102 | } | 102 | } |
103 | 103 | ||
104 | // TODO once Def::Item is gone, this should be able to always return a NavigationTarget | 104 | pub(crate) fn from_field(db: &RootDatabase, field: hir::StructField) -> NavigationTarget { |
105 | pub(crate) fn from_def( | 105 | let (file_id, field) = field.source(db); |
106 | db: &RootDatabase, | 106 | let file_id = file_id.original_file(db); |
107 | module_def: hir::ModuleDef, | 107 | match field { |
108 | ) -> Option<NavigationTarget> { | 108 | FieldSource::Named(it) => NavigationTarget::from_named(file_id, &*it), |
109 | FieldSource::Pos(it) => { | ||
110 | NavigationTarget::from_syntax(file_id, "".into(), None, it.syntax()) | ||
111 | } | ||
112 | } | ||
113 | } | ||
114 | |||
115 | pub(crate) fn from_def(db: &RootDatabase, module_def: hir::ModuleDef) -> NavigationTarget { | ||
109 | match module_def { | 116 | match module_def { |
110 | hir::ModuleDef::Module(module) => Some(NavigationTarget::from_module(db, module)), | 117 | hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module), |
111 | hir::ModuleDef::Function(func) => Some(NavigationTarget::from_function(db, func)), | 118 | hir::ModuleDef::Function(func) => NavigationTarget::from_function(db, func), |
112 | hir::ModuleDef::Struct(s) => { | 119 | hir::ModuleDef::Struct(s) => { |
113 | let (file_id, node) = s.source(db); | 120 | let (file_id, node) = s.source(db); |
114 | Some(NavigationTarget::from_named( | 121 | NavigationTarget::from_named(file_id.original_file(db), &*node) |
115 | file_id.original_file(db), | ||
116 | &*node, | ||
117 | )) | ||
118 | } | 122 | } |
119 | hir::ModuleDef::Const(s) => { | 123 | hir::ModuleDef::Const(s) => { |
120 | let (file_id, node) = s.source(db); | 124 | let (file_id, node) = s.source(db); |
121 | Some(NavigationTarget::from_named( | 125 | NavigationTarget::from_named(file_id.original_file(db), &*node) |
122 | file_id.original_file(db), | ||
123 | &*node, | ||
124 | )) | ||
125 | } | 126 | } |
126 | hir::ModuleDef::Static(s) => { | 127 | hir::ModuleDef::Static(s) => { |
127 | let (file_id, node) = s.source(db); | 128 | let (file_id, node) = s.source(db); |
128 | Some(NavigationTarget::from_named( | 129 | NavigationTarget::from_named(file_id.original_file(db), &*node) |
129 | file_id.original_file(db), | ||
130 | &*node, | ||
131 | )) | ||
132 | } | 130 | } |
133 | hir::ModuleDef::Enum(e) => { | 131 | hir::ModuleDef::Enum(e) => { |
134 | let (file_id, node) = e.source(db); | 132 | let (file_id, node) = e.source(db); |
135 | Some(NavigationTarget::from_named( | 133 | NavigationTarget::from_named(file_id.original_file(db), &*node) |
136 | file_id.original_file(db), | ||
137 | &*node, | ||
138 | )) | ||
139 | } | 134 | } |
140 | hir::ModuleDef::EnumVariant(var) => { | 135 | hir::ModuleDef::EnumVariant(var) => { |
141 | let (file_id, node) = var.source(db); | 136 | let (file_id, node) = var.source(db); |
142 | Some(NavigationTarget::from_named( | 137 | NavigationTarget::from_named(file_id.original_file(db), &*node) |
143 | file_id.original_file(db), | ||
144 | &*node, | ||
145 | )) | ||
146 | } | 138 | } |
147 | hir::ModuleDef::Trait(e) => { | 139 | hir::ModuleDef::Trait(e) => { |
148 | let (file_id, node) = e.source(db); | 140 | let (file_id, node) = e.source(db); |
149 | Some(NavigationTarget::from_named( | 141 | NavigationTarget::from_named(file_id.original_file(db), &*node) |
150 | file_id.original_file(db), | ||
151 | &*node, | ||
152 | )) | ||
153 | } | 142 | } |
154 | hir::ModuleDef::Type(e) => { | 143 | hir::ModuleDef::Type(e) => { |
155 | let (file_id, node) = e.source(db); | 144 | let (file_id, node) = e.source(db); |
156 | Some(NavigationTarget::from_named( | 145 | NavigationTarget::from_named(file_id.original_file(db), &*node) |
157 | file_id.original_file(db), | ||
158 | &*node, | ||
159 | )) | ||
160 | } | 146 | } |
161 | } | 147 | } |
162 | } | 148 | } |
diff --git a/crates/ra_ide_api/src/rename.rs b/crates/ra_ide_api/src/rename.rs index 5b767addd..db5ccf969 100644 --- a/crates/ra_ide_api/src/rename.rs +++ b/crates/ra_ide_api/src/rename.rs | |||
@@ -17,7 +17,7 @@ use crate::{ | |||
17 | SourceChange, | 17 | SourceChange, |
18 | SourceFileEdit, | 18 | SourceFileEdit, |
19 | }; | 19 | }; |
20 | use ra_db::{FilesDatabase, SyntaxDatabase}; | 20 | use ra_db::SourceDatabase; |
21 | use relative_path::RelativePath; | 21 | use relative_path::RelativePath; |
22 | 22 | ||
23 | pub(crate) fn rename( | 23 | pub(crate) fn rename( |
@@ -25,7 +25,7 @@ pub(crate) fn rename( | |||
25 | position: FilePosition, | 25 | position: FilePosition, |
26 | new_name: &str, | 26 | new_name: &str, |
27 | ) -> Option<SourceChange> { | 27 | ) -> Option<SourceChange> { |
28 | let source_file = db.source_file(position.file_id); | 28 | let source_file = db.parse(position.file_id); |
29 | let syntax = source_file.syntax(); | 29 | let syntax = source_file.syntax(); |
30 | 30 | ||
31 | if let Some((ast_name, ast_module)) = find_name_and_module_at_offset(syntax, position) { | 31 | if let Some((ast_name, ast_module)) = find_name_and_module_at_offset(syntax, position) { |
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs index 0f9f8deb3..dc8c40ea6 100644 --- a/crates/ra_ide_api/src/runnables.rs +++ b/crates/ra_ide_api/src/runnables.rs | |||
@@ -3,7 +3,7 @@ use ra_syntax::{ | |||
3 | TextRange, SyntaxNode, | 3 | TextRange, SyntaxNode, |
4 | ast::{self, AstNode, NameOwner, ModuleItemOwner}, | 4 | ast::{self, AstNode, NameOwner, ModuleItemOwner}, |
5 | }; | 5 | }; |
6 | use ra_db::SyntaxDatabase; | 6 | use ra_db::SourceDatabase; |
7 | 7 | ||
8 | use crate::{db::RootDatabase, FileId}; | 8 | use crate::{db::RootDatabase, FileId}; |
9 | 9 | ||
@@ -22,7 +22,7 @@ pub enum RunnableKind { | |||
22 | } | 22 | } |
23 | 23 | ||
24 | pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { | 24 | pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { |
25 | let source_file = db.source_file(file_id); | 25 | let source_file = db.parse(file_id); |
26 | source_file | 26 | source_file |
27 | .syntax() | 27 | .syntax() |
28 | .descendants() | 28 | .descendants() |
diff --git a/crates/ra_ide_api/src/status.rs b/crates/ra_ide_api/src/status.rs index 717537fcd..e11eed223 100644 --- a/crates/ra_ide_api/src/status.rs +++ b/crates/ra_ide_api/src/status.rs | |||
@@ -6,7 +6,7 @@ use std::{ | |||
6 | 6 | ||
7 | use ra_syntax::{AstNode, TreeArc, SourceFile}; | 7 | use ra_syntax::{AstNode, TreeArc, SourceFile}; |
8 | use ra_db::{ | 8 | use ra_db::{ |
9 | SourceFileQuery, FileTextQuery, SourceRootId, | 9 | ParseQuery, FileTextQuery, SourceRootId, |
10 | salsa::{Database, debug::{DebugQueryTable, TableEntry}}, | 10 | salsa::{Database, debug::{DebugQueryTable, TableEntry}}, |
11 | }; | 11 | }; |
12 | 12 | ||
@@ -17,7 +17,7 @@ use crate::{ | |||
17 | 17 | ||
18 | pub(crate) fn status(db: &RootDatabase) -> String { | 18 | pub(crate) fn status(db: &RootDatabase) -> String { |
19 | let files_stats = db.query(FileTextQuery).entries::<FilesStats>(); | 19 | let files_stats = db.query(FileTextQuery).entries::<FilesStats>(); |
20 | let syntax_tree_stats = db.query(SourceFileQuery).entries::<SyntaxTreeStats>(); | 20 | let syntax_tree_stats = db.query(ParseQuery).entries::<SyntaxTreeStats>(); |
21 | let symbols_stats = db | 21 | let symbols_stats = db |
22 | .query(LibrarySymbolsQuery) | 22 | .query(LibrarySymbolsQuery) |
23 | .entries::<LibrarySymbolsStats>(); | 23 | .entries::<LibrarySymbolsStats>(); |
@@ -94,17 +94,12 @@ impl FromIterator<TableEntry<FileId, TreeArc<SourceFile>>> for SyntaxTreeStats { | |||
94 | #[derive(Default)] | 94 | #[derive(Default)] |
95 | struct LibrarySymbolsStats { | 95 | struct LibrarySymbolsStats { |
96 | total: usize, | 96 | total: usize, |
97 | fst_size: Bytes, | 97 | size: Bytes, |
98 | symbols_size: Bytes, | ||
99 | } | 98 | } |
100 | 99 | ||
101 | impl fmt::Display for LibrarySymbolsStats { | 100 | impl fmt::Display for LibrarySymbolsStats { |
102 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | 101 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
103 | write!( | 102 | write!(fmt, "{} ({}) symbols", self.total, self.size,) |
104 | fmt, | ||
105 | "{} ({} + {}) symbols", | ||
106 | self.total, self.fst_size, self.symbols_size | ||
107 | ) | ||
108 | } | 103 | } |
109 | } | 104 | } |
110 | 105 | ||
@@ -117,8 +112,7 @@ impl FromIterator<TableEntry<SourceRootId, Arc<SymbolIndex>>> for LibrarySymbols | |||
117 | for entry in iter { | 112 | for entry in iter { |
118 | let value = entry.value.unwrap(); | 113 | let value = entry.value.unwrap(); |
119 | res.total += value.len(); | 114 | res.total += value.len(); |
120 | res.fst_size += value.fst_size(); | 115 | res.size += value.memory_size(); |
121 | res.symbols_size += value.symbols_size(); | ||
122 | } | 116 | } |
123 | res | 117 | res |
124 | } | 118 | } |
diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide_api/src/symbol_index.rs index 69a669b8d..72c93f530 100644 --- a/crates/ra_ide_api/src/symbol_index.rs +++ b/crates/ra_ide_api/src/symbol_index.rs | |||
@@ -34,7 +34,7 @@ use ra_syntax::{ | |||
34 | ast::{self, NameOwner}, | 34 | ast::{self, NameOwner}, |
35 | }; | 35 | }; |
36 | use ra_db::{ | 36 | use ra_db::{ |
37 | SourceRootId, FilesDatabase, | 37 | SourceRootId, SourceDatabase, |
38 | salsa::{self, ParallelDatabase}, | 38 | salsa::{self, ParallelDatabase}, |
39 | }; | 39 | }; |
40 | use rayon::prelude::*; | 40 | use rayon::prelude::*; |
@@ -44,16 +44,24 @@ use crate::{ | |||
44 | db::RootDatabase, | 44 | db::RootDatabase, |
45 | }; | 45 | }; |
46 | 46 | ||
47 | #[salsa::query_group] | 47 | #[salsa::query_group(SymbolsDatabaseStorage)] |
48 | pub(crate) trait SymbolsDatabase: hir::db::HirDatabase { | 48 | pub(crate) trait SymbolsDatabase: hir::db::HirDatabase { |
49 | fn file_symbols(&self, file_id: FileId) -> Arc<SymbolIndex>; | 49 | fn file_symbols(&self, file_id: FileId) -> Arc<SymbolIndex>; |
50 | #[salsa::input] | 50 | #[salsa::input] |
51 | fn library_symbols(&self, id: SourceRootId) -> Arc<SymbolIndex>; | 51 | fn library_symbols(&self, id: SourceRootId) -> Arc<SymbolIndex>; |
52 | /// The set of "local" (that is, from the current workspace) roots. | ||
53 | /// Files in local roots are assumed to change frequently. | ||
54 | #[salsa::input] | ||
55 | fn local_roots(&self) -> Arc<Vec<SourceRootId>>; | ||
56 | /// The set of roots for crates.io libraries. | ||
57 | /// Files in libraries are assumed to never change. | ||
58 | #[salsa::input] | ||
59 | fn library_roots(&self) -> Arc<Vec<SourceRootId>>; | ||
52 | } | 60 | } |
53 | 61 | ||
54 | fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> { | 62 | fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> { |
55 | db.check_canceled(); | 63 | db.check_canceled(); |
56 | let source_file = db.source_file(file_id); | 64 | let source_file = db.parse(file_id); |
57 | let mut symbols = source_file | 65 | let mut symbols = source_file |
58 | .syntax() | 66 | .syntax() |
59 | .descendants() | 67 | .descendants() |
@@ -137,12 +145,8 @@ impl SymbolIndex { | |||
137 | self.symbols.len() | 145 | self.symbols.len() |
138 | } | 146 | } |
139 | 147 | ||
140 | pub(crate) fn fst_size(&self) -> usize { | 148 | pub(crate) fn memory_size(&self) -> usize { |
141 | self.map.as_fst().size() | 149 | self.map.as_fst().size() + self.symbols.len() * mem::size_of::<FileSymbol>() |
142 | } | ||
143 | |||
144 | pub(crate) fn symbols_size(&self) -> usize { | ||
145 | self.symbols.len() * mem::size_of::<FileSymbol>() | ||
146 | } | 150 | } |
147 | 151 | ||
148 | pub(crate) fn for_files( | 152 | pub(crate) fn for_files( |
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index a4d3ad005..26bde495b 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use ra_syntax::{ast, AstNode,}; | 1 | use ra_syntax::{ast, AstNode,}; |
2 | use ra_db::SyntaxDatabase; | 2 | use ra_db::SourceDatabase; |
3 | 3 | ||
4 | use crate::{ | 4 | use crate::{ |
5 | FileId, HighlightedRange, | 5 | FileId, HighlightedRange, |
@@ -7,7 +7,7 @@ use crate::{ | |||
7 | }; | 7 | }; |
8 | 8 | ||
9 | pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> { | 9 | pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> { |
10 | let source_file = db.source_file(file_id); | 10 | let source_file = db.parse(file_id); |
11 | let mut res = ra_ide_api_light::highlight(source_file.syntax()); | 11 | let mut res = ra_ide_api_light::highlight(source_file.syntax()); |
12 | for macro_call in source_file | 12 | for macro_call in source_file |
13 | .syntax() | 13 | .syntax() |