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/src/assists.rs5
-rw-r--r--crates/ra_ide_api/src/call_info.rs38
-rw-r--r--crates/ra_ide_api/src/change.rs39
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs4
-rw-r--r--crates/ra_ide_api/src/completion/complete_fn_param.rs9
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs12
-rw-r--r--crates/ra_ide_api/src/completion/complete_postfix.rs6
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs10
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs8
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs16
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs12
-rw-r--r--crates/ra_ide_api/src/extend_selection.rs4
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs40
-rw-r--r--crates/ra_ide_api/src/hover.rs14
-rw-r--r--crates/ra_ide_api/src/impls.rs24
-rw-r--r--crates/ra_ide_api/src/lib.rs24
-rw-r--r--crates/ra_ide_api/src/mock_analysis.rs9
-rw-r--r--crates/ra_ide_api/src/navigation_target.rs10
-rw-r--r--crates/ra_ide_api/src/references.rs4
-rw-r--r--crates/ra_ide_api/src/runnables.rs31
-rw-r--r--crates/ra_ide_api/src/status.rs21
-rw-r--r--crates/ra_ide_api/src/symbol_index.rs5
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs16
23 files changed, 87 insertions, 274 deletions
diff --git a/crates/ra_ide_api/src/assists.rs b/crates/ra_ide_api/src/assists.rs
index 2a96fdf47..7a9c66681 100644
--- a/crates/ra_ide_api/src/assists.rs
+++ b/crates/ra_ide_api/src/assists.rs
@@ -7,10 +7,7 @@ pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec<SourceChange>
7 .into_iter() 7 .into_iter()
8 .map(|(label, action)| { 8 .map(|(label, action)| {
9 let file_id = frange.file_id; 9 let file_id = frange.file_id;
10 let file_edit = SourceFileEdit { 10 let file_edit = SourceFileEdit { file_id, edit: action.edit };
11 file_id,
12 edit: action.edit,
13 };
14 SourceChange { 11 SourceChange {
15 label: label.label, 12 label: label.label,
16 source_file_edits: vec![file_edit], 13 source_file_edits: vec![file_edit],
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index a59ab7853..1b279615c 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -21,9 +21,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
21 21
22 // Resolve the function's NameRef (NOTE: this isn't entirely accurate). 22 // Resolve the function's NameRef (NOTE: this isn't entirely accurate).
23 let file_symbols = crate::symbol_index::index_resolve(db, name_ref); 23 let file_symbols = crate::symbol_index::index_resolve(db, name_ref);
24 let symbol = file_symbols 24 let symbol = file_symbols.into_iter().find(|it| it.ptr.kind() == FN_DEF)?;
25 .into_iter()
26 .find(|it| it.ptr.kind() == FN_DEF)?;
27 let fn_file = db.parse(symbol.file_id); 25 let fn_file = db.parse(symbol.file_id);
28 let fn_def = symbol.ptr.to_node(&fn_file); 26 let fn_def = symbol.ptr.to_node(&fn_file);
29 let fn_def = ast::FnDef::cast(fn_def).unwrap(); 27 let fn_def = ast::FnDef::cast(fn_def).unwrap();
@@ -53,13 +51,8 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
53 let start = arg_list_range.start(); 51 let start = arg_list_range.start();
54 52
55 let range_search = TextRange::from_to(start, position.offset); 53 let range_search = TextRange::from_to(start, position.offset);
56 let mut commas: usize = arg_list 54 let mut commas: usize =
57 .syntax() 55 arg_list.syntax().text().slice(range_search).to_string().matches(',').count();
58 .text()
59 .slice(range_search)
60 .to_string()
61 .matches(',')
62 .count();
63 56
64 // If we have a method call eat the first param since it's just self. 57 // If we have a method call eat the first param since it's just self.
65 if has_self { 58 if has_self {
@@ -96,11 +89,9 @@ impl<'a> FnCallNode<'a> {
96 _ => return None, 89 _ => return None,
97 }), 90 }),
98 91
99 FnCallNode::MethodCallExpr(call_expr) => call_expr 92 FnCallNode::MethodCallExpr(call_expr) => {
100 .syntax() 93 call_expr.syntax().children().filter_map(ast::NameRef::cast).nth(0)
101 .children() 94 }
102 .filter_map(ast::NameRef::cast)
103 .nth(0),
104 } 95 }
105 } 96 }
106 97
@@ -117,12 +108,7 @@ impl CallInfo {
117 let label = crate::completion::function_label(node)?; 108 let label = crate::completion::function_label(node)?;
118 let doc = function.docs(db); 109 let doc = function.docs(db);
119 110
120 Some(CallInfo { 111 Some(CallInfo { parameters: param_list(node), label, doc, active_parameter: None })
121 parameters: param_list(node),
122 label,
123 doc,
124 active_parameter: None,
125 })
126 } 112 }
127} 113}
128 114
@@ -136,10 +122,7 @@ fn param_list(node: &ast::FnDef) -> Vec<String> {
136 // Maybe use param.pat here? See if we can just extract the name? 122 // Maybe use param.pat here? See if we can just extract the name?
137 //res.extend(param_list.params().map(|p| p.syntax().text().to_string())); 123 //res.extend(param_list.params().map(|p| p.syntax().text().to_string()));
138 res.extend( 124 res.extend(
139 param_list 125 param_list.params().filter_map(|p| p.pat()).map(|pat| pat.syntax().text().to_string()),
140 .params()
141 .filter_map(|p| p.pat())
142 .map(|pat| pat.syntax().text().to_string()),
143 ); 126 );
144 } 127 }
145 res 128 res
@@ -378,10 +361,7 @@ pub fn foo() {
378"#, 361"#,
379 ); 362 );
380 363
381 assert_eq!( 364 assert_eq!(info.parameters, vec!["&mut self".to_string(), "ctx".to_string()]);
382 info.parameters,
383 vec!["&mut self".to_string(), "ctx".to_string()]
384 );
385 assert_eq!(info.active_parameter, Some(1)); 365 assert_eq!(info.active_parameter, Some(1));
386 assert_eq!( 366 assert_eq!(
387 info.doc.map(|it| it.into()), 367 info.doc.map(|it| it.into()),
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 992955740..3f041f9c3 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -65,16 +65,8 @@ impl AnalysisChange {
65 path: RelativePathBuf, 65 path: RelativePathBuf,
66 text: Arc<String>, 66 text: Arc<String>,
67 ) { 67 ) {
68 let file = AddFile { 68 let file = AddFile { file_id, path, text };
69 file_id, 69 self.roots_changed.entry(root_id).or_default().added.push(file);
70 path,
71 text,
72 };
73 self.roots_changed
74 .entry(root_id)
75 .or_default()
76 .added
77 .push(file);
78 } 70 }
79 71
80 pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) { 72 pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) {
@@ -83,11 +75,7 @@ impl AnalysisChange {
83 75
84 pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) { 76 pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) {
85 let file = RemoveFile { file_id, path }; 77 let file = RemoveFile { file_id, path };
86 self.roots_changed 78 self.roots_changed.entry(root_id).or_default().removed.push(file);
87 .entry(root_id)
88 .or_default()
89 .removed
90 .push(file);
91 } 79 }
92 80
93 pub fn add_library(&mut self, data: LibraryData) { 81 pub fn add_library(&mut self, data: LibraryData) {
@@ -155,17 +143,9 @@ impl LibraryData {
155 let mut root_change = RootChange::default(); 143 let mut root_change = RootChange::default();
156 root_change.added = files 144 root_change.added = files
157 .into_iter() 145 .into_iter()
158 .map(|(file_id, path, text)| AddFile { 146 .map(|(file_id, path, text)| AddFile { file_id, path, text })
159 file_id,
160 path,
161 text,
162 })
163 .collect(); 147 .collect();
164 LibraryData { 148 LibraryData { root_id, root_change, symbol_index }
165 root_id,
166 root_change,
167 symbol_index,
168 }
169 } 149 }
170} 150}
171 151
@@ -226,10 +206,7 @@ impl RootDatabase {
226 self.last_gc_check = time::Instant::now(); 206 self.last_gc_check = time::Instant::now();
227 let retained_trees = syntax_tree_stats(self).retained; 207 let retained_trees = syntax_tree_stats(self).retained;
228 if retained_trees > 100 { 208 if retained_trees > 100 {
229 log::info!( 209 log::info!("automatic garbadge collection, {} retained trees", retained_trees);
230 "automatic garbadge collection, {} retained trees",
231 retained_trees
232 );
233 self.collect_garbage(); 210 self.collect_garbage();
234 } 211 }
235 } 212 }
@@ -238,9 +215,7 @@ impl RootDatabase {
238 pub(crate) fn collect_garbage(&mut self) { 215 pub(crate) fn collect_garbage(&mut self) {
239 self.last_gc = time::Instant::now(); 216 self.last_gc = time::Instant::now();
240 217
241 let sweep = SweepStrategy::default() 218 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
242 .discard_values()
243 .sweep_all_revisions();
244 219
245 self.query(ra_db::ParseQuery).sweep(sweep); 220 self.query(ra_db::ParseQuery).sweep(sweep);
246 221
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index bad51cc51..a673dbdcf 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -25,9 +25,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
25fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { 25fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
26 for receiver in receiver.autoderef(ctx.db) { 26 for receiver in receiver.autoderef(ctx.db) {
27 match receiver { 27 match receiver {
28 Ty::Adt { 28 Ty::Adt { def_id, ref substs, .. } => {
29 def_id, ref substs, ..
30 } => {
31 match def_id { 29 match def_id {
32 AdtDef::Struct(s) => { 30 AdtDef::Struct(s) => {
33 for field in s.fields(ctx.db) { 31 for field in s.fields(ctx.db) {
diff --git a/crates/ra_ide_api/src/completion/complete_fn_param.rs b/crates/ra_ide_api/src/completion/complete_fn_param.rs
index 8d4df4ea1..43532226f 100644
--- a/crates/ra_ide_api/src/completion/complete_fn_param.rs
+++ b/crates/ra_ide_api/src/completion/complete_fn_param.rs
@@ -43,13 +43,12 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
43 node: &'a N, 43 node: &'a N,
44 params: &mut FxHashMap<String, (u32, &'a ast::Param)>, 44 params: &mut FxHashMap<String, (u32, &'a ast::Param)>,
45 ) { 45 ) {
46 node.functions() 46 node.functions().filter_map(|it| it.param_list()).flat_map(|it| it.params()).for_each(
47 .filter_map(|it| it.param_list()) 47 |param| {
48 .flat_map(|it| it.params())
49 .for_each(|param| {
50 let text = param.syntax().text().to_string(); 48 let text = param.syntax().text().to_string();
51 params.entry(text).or_insert((0, param)).0 += 1; 49 params.entry(text).or_insert((0, param)).0 += 1;
52 }) 50 },
51 )
53 } 52 }
54} 53}
55 54
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 0b9948d4b..c47a14e9f 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -31,14 +31,10 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
31 hir::ModuleDef::Enum(e) => { 31 hir::ModuleDef::Enum(e) => {
32 e.variants(ctx.db).into_iter().for_each(|variant| { 32 e.variants(ctx.db).into_iter().for_each(|variant| {
33 if let Some(name) = variant.name(ctx.db) { 33 if let Some(name) = variant.name(ctx.db) {
34 let detail_types = variant 34 let detail_types =
35 .fields(ctx.db) 35 variant.fields(ctx.db).into_iter().map(|field| field.ty(ctx.db));
36 .into_iter() 36 let detail =
37 .map(|field| field.ty(ctx.db)); 37 join(detail_types).separator(", ").surround_with("(", ")").to_string();
38 let detail = join(detail_types)
39 .separator(", ")
40 .surround_with("(", ")")
41 .to_string();
42 38
43 CompletionItem::new( 39 CompletionItem::new(
44 CompletionKind::Reference, 40 CompletionKind::Reference,
diff --git a/crates/ra_ide_api/src/completion/complete_postfix.rs b/crates/ra_ide_api/src/completion/complete_postfix.rs
index e3a739d6d..10a3c8db7 100644
--- a/crates/ra_ide_api/src/completion/complete_postfix.rs
+++ b/crates/ra_ide_api/src/completion/complete_postfix.rs
@@ -17,11 +17,7 @@ use ra_text_edit::TextEditBuilder;
17 17
18fn postfix_snippet(ctx: &CompletionContext, label: &str, snippet: &str) -> Builder { 18fn postfix_snippet(ctx: &CompletionContext, label: &str, snippet: &str) -> Builder {
19 let replace_range = ctx.source_range(); 19 let replace_range = ctx.source_range();
20 let receiver_range = ctx 20 let receiver_range = ctx.dot_receiver.expect("no receiver available").syntax().range();
21 .dot_receiver
22 .expect("no receiver available")
23 .syntax()
24 .range();
25 let delete_range = TextRange::from_to(receiver_range.start(), replace_range.start()); 21 let delete_range = TextRange::from_to(receiver_range.start(), replace_range.start());
26 let mut builder = TextEditBuilder::default(); 22 let mut builder = TextEditBuilder::default();
27 builder.delete(delete_range); 23 builder.delete(delete_range);
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
index 8674b1e66..445788407 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -7,13 +7,9 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
7 let names = ctx.resolver.all_names(); 7 let names = ctx.resolver.all_names();
8 8
9 names.into_iter().for_each(|(name, res)| { 9 names.into_iter().for_each(|(name, res)| {
10 CompletionItem::new( 10 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
11 CompletionKind::Reference, 11 .from_resolution(ctx, &res)
12 ctx.source_range(), 12 .add_to(acc)
13 name.to_string(),
14 )
15 .from_resolution(ctx, &res)
16 .add_to(acc)
17 }); 13 });
18} 14}
19 15
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index 8abab0221..82bd4d606 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -108,12 +108,8 @@ impl<'a> CompletionContext<'a> {
108 } 108 }
109 fn classify_name_ref(&mut self, original_file: &'a SourceFile, name_ref: &ast::NameRef) { 109 fn classify_name_ref(&mut self, original_file: &'a SourceFile, name_ref: &ast::NameRef) {
110 let name_range = name_ref.syntax().range(); 110 let name_range = name_ref.syntax().range();
111 let top_node = name_ref 111 let top_node =
112 .syntax() 112 name_ref.syntax().ancestors().take_while(|it| it.range() == name_range).last().unwrap();
113 .ancestors()
114 .take_while(|it| it.range() == name_range)
115 .last()
116 .unwrap();
117 113
118 match top_node.parent().map(|it| it.kind()) { 114 match top_node.parent().map(|it| it.kind()) {
119 Some(SOURCE_FILE) | Some(ITEM_LIST) => { 115 Some(SOURCE_FILE) | Some(ITEM_LIST) => {
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs
index 92e6e78bf..7b8972af0 100644
--- a/crates/ra_ide_api/src/completion/completion_item.rs
+++ b/crates/ra_ide_api/src/completion/completion_item.rs
@@ -105,10 +105,7 @@ impl CompletionItem {
105 } 105 }
106 /// What string is used for filtering. 106 /// What string is used for filtering.
107 pub fn lookup(&self) -> &str { 107 pub fn lookup(&self) -> &str {
108 self.lookup 108 self.lookup.as_ref().map(|it| it.as_str()).unwrap_or_else(|| self.label())
109 .as_ref()
110 .map(|it| it.as_str())
111 .unwrap_or_else(|| self.label())
112 } 109 }
113 110
114 pub fn insert_text_format(&self) -> InsertTextFormat { 111 pub fn insert_text_format(&self) -> InsertTextFormat {
@@ -214,10 +211,7 @@ impl Builder {
214 ) -> Builder { 211 ) -> Builder {
215 use hir::ModuleDef::*; 212 use hir::ModuleDef::*;
216 213
217 let def = resolution 214 let def = resolution.as_ref().take_types().or_else(|| resolution.as_ref().take_values());
218 .as_ref()
219 .take_types()
220 .or_else(|| resolution.as_ref().take_values());
221 let def = match def { 215 let def = match def {
222 None => return self, 216 None => return self,
223 Some(it) => it, 217 Some(it) => it,
@@ -323,10 +317,8 @@ pub(crate) fn check_completion(test_name: &str, code: &str, kind: CompletionKind
323 }; 317 };
324 let completions = completions(&analysis.db, position).unwrap(); 318 let completions = completions(&analysis.db, position).unwrap();
325 let completion_items: Vec<CompletionItem> = completions.into(); 319 let completion_items: Vec<CompletionItem> = completions.into();
326 let mut kind_completions: Vec<CompletionItem> = completion_items 320 let mut kind_completions: Vec<CompletionItem> =
327 .into_iter() 321 completion_items.into_iter().filter(|c| c.completion_kind == kind).collect();
328 .filter(|c| c.completion_kind == kind)
329 .collect();
330 kind_completions.sort_by_key(|c| c.label.clone()); 322 kind_completions.sort_by_key(|c| c.label.clone());
331 assert_debug_snapshot_matches!(test_name, kind_completions); 323 assert_debug_snapshot_matches!(test_name, kind_completions);
332} 324}
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index a499ac7c6..53d95fb4c 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -21,10 +21,8 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
21 let source_root = db.file_source_root(file_id); 21 let source_root = db.file_source_root(file_id);
22 let diag = match problem { 22 let diag = match problem {
23 Problem::UnresolvedModule { candidate } => { 23 Problem::UnresolvedModule { candidate } => {
24 let create_file = FileSystemEdit::CreateFile { 24 let create_file =
25 source_root, 25 FileSystemEdit::CreateFile { source_root, path: candidate.clone() };
26 path: candidate.clone(),
27 };
28 let fix = SourceChange { 26 let fix = SourceChange {
29 label: "create module".to_string(), 27 label: "create module".to_string(),
30 source_file_edits: Vec::new(), 28 source_file_edits: Vec::new(),
@@ -44,10 +42,8 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
44 dst_source_root: source_root, 42 dst_source_root: source_root,
45 dst_path: move_to.clone(), 43 dst_path: move_to.clone(),
46 }; 44 };
47 let create_file = FileSystemEdit::CreateFile { 45 let create_file =
48 source_root, 46 FileSystemEdit::CreateFile { source_root, path: move_to.join(candidate) };
49 path: move_to.join(candidate),
50 };
51 let fix = SourceChange { 47 let fix = SourceChange {
52 label: "move file and create module".to_string(), 48 label: "move file and create module".to_string(),
53 source_file_edits: Vec::new(), 49 source_file_edits: Vec::new(),
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs
index f61feaf1b..4051728e1 100644
--- a/crates/ra_ide_api/src/extend_selection.rs
+++ b/crates/ra_ide_api/src/extend_selection.rs
@@ -31,9 +31,7 @@ fn extend_selection_in_macro(
31} 31}
32 32
33fn find_macro_call(node: &SyntaxNode, range: TextRange) -> Option<&ast::MacroCall> { 33fn find_macro_call(node: &SyntaxNode, range: TextRange) -> Option<&ast::MacroCall> {
34 find_covering_node(node, range) 34 find_covering_node(node, range).ancestors().find_map(ast::MacroCall::cast)
35 .ancestors()
36 .find_map(ast::MacroCall::cast)
37} 35}
38 36
39#[cfg(test)] 37#[cfg(test)]
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 69f2d2bf6..413720960 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -50,18 +50,13 @@ pub(crate) fn reference_definition(
50 hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax()) 50 hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax())
51 { 51 {
52 // Check if it is a method 52 // Check if it is a method
53 if let Some(method_call) = name_ref 53 if let Some(method_call) = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast) {
54 .syntax()
55 .parent()
56 .and_then(ast::MethodCallExpr::cast)
57 {
58 tested_by!(goto_definition_works_for_methods); 54 tested_by!(goto_definition_works_for_methods);
59 let infer_result = function.infer(db); 55 let infer_result = function.infer(db);
60 let syntax_mapping = function.body_syntax_mapping(db); 56 let syntax_mapping = function.body_syntax_mapping(db);
61 let expr = ast::Expr::cast(method_call.syntax()).unwrap(); 57 let expr = ast::Expr::cast(method_call.syntax()).unwrap();
62 if let Some(func) = syntax_mapping 58 if let Some(func) =
63 .node_expr(expr) 59 syntax_mapping.node_expr(expr).and_then(|it| infer_result.method_resolution(it))
64 .and_then(|it| infer_result.method_resolution(it))
65 { 60 {
66 return Exact(NavigationTarget::from_function(db, func)); 61 return Exact(NavigationTarget::from_function(db, func));
67 }; 62 };
@@ -72,9 +67,8 @@ pub(crate) fn reference_definition(
72 let infer_result = function.infer(db); 67 let infer_result = function.infer(db);
73 let syntax_mapping = function.body_syntax_mapping(db); 68 let syntax_mapping = function.body_syntax_mapping(db);
74 let expr = ast::Expr::cast(field_expr.syntax()).unwrap(); 69 let expr = ast::Expr::cast(field_expr.syntax()).unwrap();
75 if let Some(field) = syntax_mapping 70 if let Some(field) =
76 .node_expr(expr) 71 syntax_mapping.node_expr(expr).and_then(|it| infer_result.field_resolution(it))
77 .and_then(|it| infer_result.field_resolution(it))
78 { 72 {
79 return Exact(NavigationTarget::from_field(db, field)); 73 return Exact(NavigationTarget::from_field(db, field));
80 }; 74 };
@@ -82,29 +76,19 @@ pub(crate) fn reference_definition(
82 } 76 }
83 // Try name resolution 77 // Try name resolution
84 let resolver = hir::source_binder::resolver_for_node(db, file_id, name_ref.syntax()); 78 let resolver = hir::source_binder::resolver_for_node(db, file_id, name_ref.syntax());
85 if let Some(path) = name_ref 79 if let Some(path) =
86 .syntax() 80 name_ref.syntax().ancestors().find_map(ast::Path::cast).and_then(hir::Path::from_ast)
87 .ancestors()
88 .find_map(ast::Path::cast)
89 .and_then(hir::Path::from_ast)
90 { 81 {
91 let resolved = resolver.resolve_path(db, &path); 82 let resolved = resolver.resolve_path(db, &path);
92 match resolved 83 match resolved.clone().take_types().or_else(|| resolved.take_values()) {
93 .clone()
94 .take_types()
95 .or_else(|| resolved.take_values())
96 {
97 Some(Resolution::Def(def)) => return Exact(NavigationTarget::from_def(db, def)), 84 Some(Resolution::Def(def)) => return Exact(NavigationTarget::from_def(db, def)),
98 Some(Resolution::LocalBinding(pat)) => { 85 Some(Resolution::LocalBinding(pat)) => {
99 let body = resolver.body().expect("no body for local binding"); 86 let body = resolver.body().expect("no body for local binding");
100 let syntax_mapping = body.syntax_mapping(db); 87 let syntax_mapping = body.syntax_mapping(db);
101 let ptr = syntax_mapping 88 let ptr =
102 .pat_syntax(pat) 89 syntax_mapping.pat_syntax(pat).expect("pattern not found in syntax mapping");
103 .expect("pattern not found in syntax mapping"); 90 let name =
104 let name = path 91 path.as_ident().cloned().expect("local binding from a multi-segment path");
105 .as_ident()
106 .cloned()
107 .expect("local binding from a multi-segment path");
108 let nav = NavigationTarget::from_scope_entry(file_id, name, ptr); 92 let nav = NavigationTarget::from_scope_entry(file_id, name, ptr);
109 return Exact(nav); 93 return Exact(nav);
110 } 94 }
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index f993a461c..60b81567c 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -33,13 +33,9 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
33 } 33 }
34 if range.is_none() { 34 if range.is_none() {
35 let node = find_leaf_at_offset(file.syntax(), position.offset).find_map(|leaf| { 35 let node = find_leaf_at_offset(file.syntax(), position.offset).find_map(|leaf| {
36 leaf.ancestors() 36 leaf.ancestors().find(|n| ast::Expr::cast(*n).is_some() || ast::Pat::cast(*n).is_some())
37 .find(|n| ast::Expr::cast(*n).is_some() || ast::Pat::cast(*n).is_some())
38 })?; 37 })?;
39 let frange = FileRange { 38 let frange = FileRange { file_id: position.file_id, range: node.range() };
40 file_id: position.file_id,
41 range: node.range(),
42 };
43 res.extend(type_of(db, frange).map(Into::into)); 39 res.extend(type_of(db, frange).map(Into::into));
44 range = Some(node.range()); 40 range = Some(node.range());
45 }; 41 };
@@ -126,10 +122,8 @@ impl NavigationTarget {
126 where 122 where
127 T: ast::NameOwner + ast::VisibilityOwner, 123 T: ast::NameOwner + ast::VisibilityOwner,
128 { 124 {
129 let mut string = node 125 let mut string =
130 .visibility() 126 node.visibility().map(|v| format!("{} ", v.syntax().text())).unwrap_or_default();
131 .map(|v| format!("{} ", v.syntax().text()))
132 .unwrap_or_default();
133 string.push_str(label); 127 string.push_str(label);
134 node.name()?.syntax().text().push_to(&mut string); 128 node.name()?.syntax().text().push_to(&mut string);
135 Some(string) 129 Some(string)
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs
index 4fb054139..444c4aeb2 100644
--- a/crates/ra_ide_api/src/impls.rs
+++ b/crates/ra_ide_api/src/impls.rs
@@ -83,9 +83,7 @@ mod tests {
83 83
84 let navs = analysis.goto_implementation(pos).unwrap().unwrap().info; 84 let navs = analysis.goto_implementation(pos).unwrap().unwrap().info;
85 assert_eq!(navs.len(), expected.len()); 85 assert_eq!(navs.len(), expected.len());
86 navs.into_iter() 86 navs.into_iter().enumerate().for_each(|(i, nav)| nav.assert_match(expected[i]));
87 .enumerate()
88 .for_each(|(i, nav)| nav.assert_match(expected[i]));
89 } 87 }
90 88
91 #[test] 89 #[test]
@@ -109,10 +107,7 @@ mod tests {
109 impl Foo {} 107 impl Foo {}
110 impl Foo {} 108 impl Foo {}
111 ", 109 ",
112 &[ 110 &["impl IMPL_BLOCK FileId(1) [12; 23)", "impl IMPL_BLOCK FileId(1) [24; 35)"],
113 "impl IMPL_BLOCK FileId(1) [12; 23)",
114 "impl IMPL_BLOCK FileId(1) [24; 35)",
115 ],
116 ); 111 );
117 } 112 }
118 113
@@ -129,10 +124,7 @@ mod tests {
129 impl super::Foo {} 124 impl super::Foo {}
130 } 125 }
131 ", 126 ",
132 &[ 127 &["impl IMPL_BLOCK FileId(1) [24; 42)", "impl IMPL_BLOCK FileId(1) [57; 75)"],
133 "impl IMPL_BLOCK FileId(1) [24; 42)",
134 "impl IMPL_BLOCK FileId(1) [57; 75)",
135 ],
136 ); 128 );
137 } 129 }
138 130
@@ -149,10 +141,7 @@ mod tests {
149 //- /b.rs 141 //- /b.rs
150 impl crate::Foo {} 142 impl crate::Foo {}
151 ", 143 ",
152 &[ 144 &["impl IMPL_BLOCK FileId(2) [0; 18)", "impl IMPL_BLOCK FileId(3) [0; 18)"],
153 "impl IMPL_BLOCK FileId(2) [0; 18)",
154 "impl IMPL_BLOCK FileId(3) [0; 18)",
155 ],
156 ); 145 );
157 } 146 }
158 147
@@ -183,10 +172,7 @@ mod tests {
183 //- /b.rs 172 //- /b.rs
184 impl crate::T for crate::Foo {} 173 impl crate::T for crate::Foo {}
185 ", 174 ",
186 &[ 175 &["impl IMPL_BLOCK FileId(2) [0; 31)", "impl IMPL_BLOCK FileId(3) [0; 31)"],
187 "impl IMPL_BLOCK FileId(2) [0; 31)",
188 "impl IMPL_BLOCK FileId(3) [0; 31)",
189 ],
190 ); 176 );
191 } 177 }
192} 178}
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 1f43b7623..2d090d9b4 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -90,15 +90,8 @@ pub struct SourceFileEdit {
90 90
91#[derive(Debug)] 91#[derive(Debug)]
92pub enum FileSystemEdit { 92pub enum FileSystemEdit {
93 CreateFile { 93 CreateFile { source_root: SourceRootId, path: RelativePathBuf },
94 source_root: SourceRootId, 94 MoveFile { src: FileId, dst_source_root: SourceRootId, dst_path: RelativePathBuf },
95 path: RelativePathBuf,
96 },
97 MoveFile {
98 src: FileId,
99 dst_source_root: SourceRootId,
100 dst_path: RelativePathBuf,
101 },
102} 95}
103 96
104#[derive(Debug)] 97#[derive(Debug)]
@@ -179,9 +172,7 @@ impl AnalysisHost {
179 /// Returns a snapshot of the current state, which you can query for 172 /// Returns a snapshot of the current state, which you can query for
180 /// semantic information. 173 /// semantic information.
181 pub fn analysis(&self) -> Analysis { 174 pub fn analysis(&self) -> Analysis {
182 Analysis { 175 Analysis { db: self.db.snapshot() }
183 db: self.db.snapshot(),
184 }
185 } 176 }
186 177
187 /// Applies changes to the current state of the world. If there are 178 /// Applies changes to the current state of the world. If there are
@@ -401,17 +392,12 @@ impl Analysis {
401 392
402impl SourceChange { 393impl SourceChange {
403 pub(crate) fn from_local_edit(file_id: FileId, edit: LocalEdit) -> SourceChange { 394 pub(crate) fn from_local_edit(file_id: FileId, edit: LocalEdit) -> SourceChange {
404 let file_edit = SourceFileEdit { 395 let file_edit = SourceFileEdit { file_id, edit: edit.edit };
405 file_id,
406 edit: edit.edit,
407 };
408 SourceChange { 396 SourceChange {
409 label: edit.label, 397 label: edit.label,
410 source_file_edits: vec![file_edit], 398 source_file_edits: vec![file_edit],
411 file_system_edits: vec![], 399 file_system_edits: vec![],
412 cursor_position: edit 400 cursor_position: edit.cursor_position.map(|offset| FilePosition { offset, file_id }),
413 .cursor_position
414 .map(|offset| FilePosition { offset, file_id }),
415 } 401 }
416 } 402 }
417} 403}
diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs
index 834b30541..8d8603062 100644
--- a/crates/ra_ide_api/src/mock_analysis.rs
+++ b/crates/ra_ide_api/src/mock_analysis.rs
@@ -41,10 +41,7 @@ impl MockAnalysis {
41 let mut res = MockAnalysis::new(); 41 let mut res = MockAnalysis::new();
42 for entry in parse_fixture(fixture) { 42 for entry in parse_fixture(fixture) {
43 if entry.text.contains(CURSOR_MARKER) { 43 if entry.text.contains(CURSOR_MARKER) {
44 assert!( 44 assert!(position.is_none(), "only one marker (<|>) per fixture is allowed");
45 position.is_none(),
46 "only one marker (<|>) per fixture is allowed"
47 );
48 position = Some(res.add_file_with_position(&entry.meta, &entry.text)); 45 position = Some(res.add_file_with_position(&entry.meta, &entry.text));
49 } else { 46 } else {
50 res.add_file(&entry.meta, &entry.text); 47 res.add_file(&entry.meta, &entry.text);
@@ -97,9 +94,7 @@ impl MockAnalysis {
97 let other_crate = crate_graph.add_crate_root(file_id); 94 let other_crate = crate_graph.add_crate_root(file_id);
98 let crate_name = path.parent().unwrap().file_name().unwrap(); 95 let crate_name = path.parent().unwrap().file_name().unwrap();
99 if let Some(root_crate) = root_crate { 96 if let Some(root_crate) = root_crate {
100 crate_graph 97 crate_graph.add_dep(root_crate, crate_name.into(), other_crate).unwrap();
101 .add_dep(root_crate, crate_name.into(), other_crate)
102 .unwrap();
103 } 98 }
104 } 99 }
105 change.add_file(source_root, file_id, path, Arc::new(contents)); 100 change.add_file(source_root, file_id, path, Arc::new(contents));
diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs
index 617908aed..a2e4b6506 100644
--- a/crates/ra_ide_api/src/navigation_target.rs
+++ b/crates/ra_ide_api/src/navigation_target.rs
@@ -72,10 +72,7 @@ impl NavigationTarget {
72 72
73 pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget { 73 pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
74 let (file_id, source) = module.definition_source(db); 74 let (file_id, source) = module.definition_source(db);
75 let name = module 75 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
76 .name(db)
77 .map(|it| it.to_string().into())
78 .unwrap_or_default();
79 match source { 76 match source {
80 ModuleSource::SourceFile(node) => { 77 ModuleSource::SourceFile(node) => {
81 NavigationTarget::from_syntax(file_id, name, None, node.syntax()) 78 NavigationTarget::from_syntax(file_id, name, None, node.syntax())
@@ -87,10 +84,7 @@ impl NavigationTarget {
87 } 84 }
88 85
89 pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget { 86 pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
90 let name = module 87 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
91 .name(db)
92 .map(|it| it.to_string().into())
93 .unwrap_or_default();
94 if let Some((file_id, source)) = module.declaration_source(db) { 88 if let Some((file_id, source)) = module.declaration_source(db) {
95 return NavigationTarget::from_syntax(file_id, name, None, source.syntax()); 89 return NavigationTarget::from_syntax(file_id, name, None, source.syntax());
96 } 90 }
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index b129f3134..2cb1cc9be 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -305,9 +305,7 @@ mod tests {
305 } 305 }
306 } 306 }
307 } 307 }
308 let result = text_edit_bulder 308 let result = text_edit_bulder.finish().apply(&*analysis.file_text(file_id.unwrap()));
309 .finish()
310 .apply(&*analysis.file_text(file_id.unwrap()));
311 assert_eq_text!(expected, &*result); 309 assert_eq_text!(expected, &*result);
312 } 310 }
313} 311}
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs
index dc8c40ea6..d64b5a4e0 100644
--- a/crates/ra_ide_api/src/runnables.rs
+++ b/crates/ra_ide_api/src/runnables.rs
@@ -23,11 +23,7 @@ pub enum RunnableKind {
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.parse(file_id); 25 let source_file = db.parse(file_id);
26 source_file 26 source_file.syntax().descendants().filter_map(|i| runnable(db, file_id, i)).collect()
27 .syntax()
28 .descendants()
29 .filter_map(|i| runnable(db, file_id, i))
30 .collect()
31} 27}
32 28
33fn runnable(db: &RootDatabase, file_id: FileId, item: &SyntaxNode) -> Option<Runnable> { 29fn runnable(db: &RootDatabase, file_id: FileId, item: &SyntaxNode) -> Option<Runnable> {
@@ -45,20 +41,13 @@ fn runnable_fn(fn_def: &ast::FnDef) -> Option<Runnable> {
45 let kind = if name == "main" { 41 let kind = if name == "main" {
46 RunnableKind::Bin 42 RunnableKind::Bin
47 } else if fn_def.has_atom_attr("test") { 43 } else if fn_def.has_atom_attr("test") {
48 RunnableKind::Test { 44 RunnableKind::Test { name: name.to_string() }
49 name: name.to_string(),
50 }
51 } else if fn_def.has_atom_attr("bench") { 45 } else if fn_def.has_atom_attr("bench") {
52 RunnableKind::Bench { 46 RunnableKind::Bench { name: name.to_string() }
53 name: name.to_string(),
54 }
55 } else { 47 } else {
56 return None; 48 return None;
57 }; 49 };
58 Some(Runnable { 50 Some(Runnable { range: fn_def.syntax().range(), kind })
59 range: fn_def.syntax().range(),
60 kind,
61 })
62} 51}
63 52
64fn runnable_mod(db: &RootDatabase, file_id: FileId, module: &ast::Module) -> Option<Runnable> { 53fn runnable_mod(db: &RootDatabase, file_id: FileId, module: &ast::Module) -> Option<Runnable> {
@@ -77,16 +66,8 @@ fn runnable_mod(db: &RootDatabase, file_id: FileId, module: &ast::Module) -> Opt
77 let module = hir::source_binder::module_from_child_node(db, file_id, module.syntax())?; 66 let module = hir::source_binder::module_from_child_node(db, file_id, module.syntax())?;
78 67
79 // FIXME: thread cancellation instead of `.ok`ing 68 // FIXME: thread cancellation instead of `.ok`ing
80 let path = module 69 let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::");
81 .path_to_root(db) 70 Some(Runnable { range, kind: RunnableKind::TestMod { path } })
82 .into_iter()
83 .rev()
84 .filter_map(|it| it.name(db))
85 .join("::");
86 Some(Runnable {
87 range,
88 kind: RunnableKind::TestMod { path },
89 })
90} 71}
91 72
92#[cfg(test)] 73#[cfg(test)]
diff --git a/crates/ra_ide_api/src/status.rs b/crates/ra_ide_api/src/status.rs
index bd355dd78..e0fc1c123 100644
--- a/crates/ra_ide_api/src/status.rs
+++ b/crates/ra_ide_api/src/status.rs
@@ -22,9 +22,7 @@ pub(crate) fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
22pub(crate) fn status(db: &RootDatabase) -> String { 22pub(crate) fn status(db: &RootDatabase) -> String {
23 let files_stats = db.query(FileTextQuery).entries::<FilesStats>(); 23 let files_stats = db.query(FileTextQuery).entries::<FilesStats>();
24 let syntax_tree_stats = syntax_tree_stats(db); 24 let syntax_tree_stats = syntax_tree_stats(db);
25 let symbols_stats = db 25 let symbols_stats = db.query(LibrarySymbolsQuery).entries::<LibrarySymbolsStats>();
26 .query(LibrarySymbolsQuery)
27 .entries::<LibrarySymbolsStats>();
28 let n_defs = { 26 let n_defs = {
29 let interner: &hir::HirInterner = db.as_ref(); 27 let interner: &hir::HirInterner = db.as_ref();
30 interner.len() 28 interner.len()
@@ -75,11 +73,7 @@ pub(crate) struct SyntaxTreeStats {
75 73
76impl fmt::Display for SyntaxTreeStats { 74impl fmt::Display for SyntaxTreeStats {
77 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 75 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
78 write!( 76 write!(fmt, "{} trees, {} ({}) retained", self.total, self.retained, self.retained_size,)
79 fmt,
80 "{} trees, {} ({}) retained",
81 self.total, self.retained, self.retained_size,
82 )
83 } 77 }
84} 78}
85 79
@@ -144,20 +138,13 @@ impl MemoryStats {
144 138
145 #[cfg(not(feature = "jemalloc"))] 139 #[cfg(not(feature = "jemalloc"))]
146 fn current() -> MemoryStats { 140 fn current() -> MemoryStats {
147 MemoryStats { 141 MemoryStats { allocated: Bytes(0), resident: Bytes(0) }
148 allocated: Bytes(0),
149 resident: Bytes(0),
150 }
151 } 142 }
152} 143}
153 144
154impl fmt::Display for MemoryStats { 145impl fmt::Display for MemoryStats {
155 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 146 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
156 write!( 147 write!(fmt, "{} allocated {} resident", self.allocated, self.resident,)
157 fmt,
158 "{} allocated {} resident",
159 self.allocated, self.resident,
160 )
161 } 148 }
162} 149}
163 150
diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide_api/src/symbol_index.rs
index 3d0b2369e..de0f46134 100644
--- a/crates/ra_ide_api/src/symbol_index.rs
+++ b/crates/ra_ide_api/src/symbol_index.rs
@@ -101,10 +101,7 @@ pub(crate) fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol>
101 } 101 }
102 102
103 let snap = Snap(db.snapshot()); 103 let snap = Snap(db.snapshot());
104 files 104 files.par_iter().map_with(snap, |db, &file_id| db.0.file_symbols(file_id)).collect()
105 .par_iter()
106 .map_with(snap, |db, &file_id| db.0.file_symbols(file_id))
107 .collect()
108 }; 105 };
109 query.search(&buf) 106 query.search(&buf)
110} 107}
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs
index 6c4391e1e..a435fe56e 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -9,20 +9,12 @@ use crate::{
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.parse(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.syntax().descendants().filter_map(ast::MacroCall::cast) {
13 .syntax()
14 .descendants()
15 .filter_map(ast::MacroCall::cast)
16 {
17 if let Some((off, exp)) = hir::MacroDef::ast_expand(macro_call) { 13 if let Some((off, exp)) = hir::MacroDef::ast_expand(macro_call) {
18 let mapped_ranges = ra_ide_api_light::highlight(&exp.syntax()) 14 let mapped_ranges =
19 .into_iter() 15 ra_ide_api_light::highlight(&exp.syntax()).into_iter().filter_map(|r| {
20 .filter_map(|r| {
21 let mapped_range = exp.map_range_back(r.range)?; 16 let mapped_range = exp.map_range_back(r.range)?;
22 let res = HighlightedRange { 17 let res = HighlightedRange { range: mapped_range + off, tag: r.tag };
23 range: mapped_range + off,
24 tag: r.tag,
25 };
26 Some(res) 18 Some(res)
27 }); 19 });
28 res.extend(mapped_ranges); 20 res.extend(mapped_ranges);