aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r--crates/ra_ide_api/Cargo.toml2
-rw-r--r--crates/ra_ide_api/src/call_info.rs6
-rw-r--r--crates/ra_ide_api/src/completion.rs4
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs8
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs51
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs2
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant.snap (renamed from crates/ra_ide_api/src/completion/snapshots/completion_item__reference_completion.snap)14
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant_with_details.snap64
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__mod_with_docs.snap26
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap12
-rw-r--r--crates/ra_ide_api/src/db.rs32
-rw-r--r--crates/ra_ide_api/src/extend_selection.rs4
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs42
-rw-r--r--crates/ra_ide_api/src/hover.rs8
-rw-r--r--crates/ra_ide_api/src/imp.rs22
-rw-r--r--crates/ra_ide_api/src/lib.rs20
-rw-r--r--crates/ra_ide_api/src/marks.rs6
-rw-r--r--crates/ra_ide_api/src/navigation_target.rs58
-rw-r--r--crates/ra_ide_api/src/rename.rs4
-rw-r--r--crates/ra_ide_api/src/runnables.rs4
-rw-r--r--crates/ra_ide_api/src/status.rs16
-rw-r--r--crates/ra_ide_api/src/symbol_index.rs22
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs4
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]
8itertools = "0.8.0" 8itertools = "0.8.0"
9join_to_string = "0.1.3"
9log = "0.4.5" 10log = "0.4.5"
10relative-path = "0.4.0" 11relative-path = "0.4.0"
11rayon = "1.0.2" 12rayon = "1.0.2"
@@ -13,7 +14,6 @@ fst = "0.3.1"
13rustc-hash = "1.0" 14rustc-hash = "1.0"
14parking_lot = "0.7.0" 15parking_lot = "0.7.0"
15unicase = "2.2.0" 16unicase = "2.2.0"
16salsa = "0.10.0-alpha3"
17 17
18ra_syntax = { path = "../ra_syntax" } 18ra_syntax = { path = "../ra_syntax" }
19ra_ide_api_light = { path = "../ra_ide_api_light" } 19ra_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 @@
1use ra_db::SyntaxDatabase; 1use ra_db::SourceDatabase;
2use ra_syntax::{ 2use 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.
12pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> { 12pub(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;
9mod complete_scope; 9mod complete_scope;
10mod complete_postfix; 10mod complete_postfix;
11 11
12use ra_db::SyntaxDatabase; 12use ra_db::SourceDatabase;
13 13
14use crate::{ 14use 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).
47pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Option<Completions> { 47pub(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 @@
1use hir::{Ty, AdtDef}; 1use hir::{Ty, AdtDef, Docs};
2 2
3use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind}; 3use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind};
4use crate::completion::completion_item::CompletionKind; 4use 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 @@
1use join_to_string::join;
2
1use crate::{ 3use 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---
2created: "2019-01-23T23:49:43.278245900+00:00" 2created: "2019-01-25T16:44:04.640545300+00:00"
3creator: [email protected].1 3creator: [email protected].2
4expression: kind_completions 4expression: kind_completions
5source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs" 5source: 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---
2created: "2019-01-25T16:44:04.641542400+00:00"
3creator: [email protected]
4expression: kind_completions
5source: 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---
2created: "2019-01-25T17:49:28.949186500+00:00"
3creator: [email protected]
4expression: kind_completions
5source: 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---
2created: "2019-01-23T13:19:23.501297515+00:00" 2created: "2019-01-25T19:27:09.519688600+00:00"
3creator: [email protected] 3creator: [email protected]
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: 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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_db::{ 3use ra_db::{
4 BaseDatabase, FileId, Canceled, 4 CheckCanceled, FileId, Canceled, SourceDatabase,
5 salsa::{self, Database}, 5 salsa,
6}; 6};
7 7
8use crate::{symbol_index, LineIndex}; 8use 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)]
18pub(crate) struct RootDatabase { 17pub(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
57impl BaseDatabase for RootDatabase {} 53impl CheckCanceled for RootDatabase {}
58 54
59impl AsRef<hir::HirInterner> for RootDatabase { 55impl 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)]
66pub(crate) trait LineIndexDatabase: ra_db::FilesDatabase + BaseDatabase { 62pub(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
70fn line_index(db: &impl ra_db::FilesDatabase, file_id: FileId) -> Arc<LineIndex> { 66fn 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 @@
1use ra_db::SyntaxDatabase; 1use ra_db::SourceDatabase;
2use ra_syntax::{ 2use 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
12pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRange { 12pub(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 @@
1use ra_db::{FileId, SyntaxDatabase}; 1use ra_db::{FileId, SourceDatabase};
2use ra_syntax::{ 2use ra_syntax::{
3 AstNode, ast, 3 AstNode, ast,
4 algo::find_node_at_offset, 4 algo::find_node_at_offset,
5}; 5};
6use test_utils::tested_by;
6 7
7use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; 8use 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)]
119mod tests { 132mod 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 @@
1use ra_db::{SyntaxDatabase}; 1use ra_db::SourceDatabase;
2use ra_syntax::{ 2use 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::{
7use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, NavigationTarget}; 7use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, NavigationTarget};
8 8
9pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeInfo<String>> { 9pub(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
55pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> { 55pub(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
89impl NavigationTarget { 89impl 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};
6use ra_db::{ 6use ra_db::{
7 FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase, 7 SourceDatabase, SourceRoot, SourceRootId,
8 salsa::Database, 8 salsa::{Database, SweepStrategy},
9}; 9};
10use ra_ide_api_light::{self, assists, LocalEdit, Severity}; 10use ra_ide_api_light::{self, assists, LocalEdit, Severity};
11use ra_syntax::{ 11use 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};
34use ra_syntax::{SourceFile, TreeArc, TextRange, TextUnit}; 34use ra_syntax::{SourceFile, TreeArc, TextRange, TextUnit};
35use ra_text_edit::TextEdit; 35use ra_text_edit::TextEdit;
36use ra_db::{ 36use ra_db::{
37 SyntaxDatabase, FilesDatabase, BaseDatabase, 37 SourceDatabase, CheckCanceled,
38 salsa::{self, ParallelDatabase}, 38 salsa::{self, ParallelDatabase},
39}; 39};
40use rayon::prelude::*; 40use 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 @@
1test_utils::marks!(inserts_parens_for_function_calls); 1test_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};
6use hir::{ModuleSource}; 6use hir::{ModuleSource, FieldSource};
7 7
8use crate::{FileSymbol, db::RootDatabase}; 8use 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};
20use ra_db::{FilesDatabase, SyntaxDatabase}; 20use ra_db::SourceDatabase;
21use relative_path::RelativePath; 21use relative_path::RelativePath;
22 22
23pub(crate) fn rename( 23pub(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};
6use ra_db::SyntaxDatabase; 6use ra_db::SourceDatabase;
7 7
8use crate::{db::RootDatabase, FileId}; 8use crate::{db::RootDatabase, FileId};
9 9
@@ -22,7 +22,7 @@ pub enum RunnableKind {
22} 22}
23 23
24pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { 24pub(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
7use ra_syntax::{AstNode, TreeArc, SourceFile}; 7use ra_syntax::{AstNode, TreeArc, SourceFile};
8use ra_db::{ 8use 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
18pub(crate) fn status(db: &RootDatabase) -> String { 18pub(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)]
95struct LibrarySymbolsStats { 95struct LibrarySymbolsStats {
96 total: usize, 96 total: usize,
97 fst_size: Bytes, 97 size: Bytes,
98 symbols_size: Bytes,
99} 98}
100 99
101impl fmt::Display for LibrarySymbolsStats { 100impl 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};
36use ra_db::{ 36use ra_db::{
37 SourceRootId, FilesDatabase, 37 SourceRootId, SourceDatabase,
38 salsa::{self, ParallelDatabase}, 38 salsa::{self, ParallelDatabase},
39}; 39};
40use rayon::prelude::*; 40use 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)]
48pub(crate) trait SymbolsDatabase: hir::db::HirDatabase { 48pub(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
54fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> { 62fn 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 @@
1use ra_syntax::{ast, AstNode,}; 1use ra_syntax::{ast, AstNode,};
2use ra_db::SyntaxDatabase; 2use ra_db::SourceDatabase;
3 3
4use crate::{ 4use crate::{
5 FileId, HighlightedRange, 5 FileId, HighlightedRange,
@@ -7,7 +7,7 @@ use crate::{
7}; 7};
8 8
9pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> { 9pub(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()