diff options
-rw-r--r-- | crates/ra_hir/src/code_model_impl/module.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/ids.rs | 38 | ||||
-rw-r--r-- | crates/ra_hir/src/module_tree.rs | 99 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/query_definitions.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 28 | ||||
-rw-r--r-- | crates/ra_ide_api/src/call_info.rs | 22 | ||||
-rw-r--r-- | crates/ra_ide_api/src/marks.rs | 1 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 28 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/project_model/cargo_workspace.rs | 10 |
12 files changed, 145 insertions, 117 deletions
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 480ec27bf..418d59c91 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs | |||
@@ -25,9 +25,10 @@ impl Module { | |||
25 | 25 | ||
26 | pub(crate) fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) { | 26 | pub(crate) fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) { |
27 | let module_tree = db.module_tree(self.krate); | 27 | let module_tree = db.module_tree(self.krate); |
28 | let source = self.module_id.source(&module_tree); | 28 | let file_id = self.module_id.file_id(&module_tree); |
29 | let module_source = ModuleSource::from_source_item_id(db, source); | 29 | let decl_id = self.module_id.decl_id(&module_tree); |
30 | let file_id = source.file_id.as_original_file(); | 30 | let module_source = ModuleSource::new(db, file_id, decl_id); |
31 | let file_id = file_id.as_original_file(); | ||
31 | (file_id, module_source) | 32 | (file_id, module_source) |
32 | } | 33 | } |
33 | 34 | ||
@@ -39,8 +40,7 @@ impl Module { | |||
39 | let link = self.module_id.parent_link(&module_tree)?; | 40 | let link = self.module_id.parent_link(&module_tree)?; |
40 | let file_id = link | 41 | let file_id = link |
41 | .owner(&module_tree) | 42 | .owner(&module_tree) |
42 | .source(&module_tree) | 43 | .file_id(&module_tree) |
43 | .file_id | ||
44 | .as_original_file(); | 44 | .as_original_file(); |
45 | let src = link.source(&module_tree, db); | 45 | let src = link.source(&module_tree, db); |
46 | Some((file_id, src)) | 46 | Some((file_id, src)) |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 5df4bd4a1..3f76b769d 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -16,6 +16,7 @@ use crate::{ | |||
16 | adt::{StructData, EnumData}, | 16 | adt::{StructData, EnumData}, |
17 | impl_block::ModuleImplBlocks, | 17 | impl_block::ModuleImplBlocks, |
18 | generics::{GenericParams, GenericDef}, | 18 | generics::{GenericParams, GenericDef}, |
19 | ids::SourceFileItemId, | ||
19 | }; | 20 | }; |
20 | 21 | ||
21 | #[salsa::query_group(HirDatabaseStorage)] | 22 | #[salsa::query_group(HirDatabaseStorage)] |
@@ -51,7 +52,11 @@ pub trait HirDatabase: SourceDatabase + AsRef<HirInterner> { | |||
51 | fn file_item(&self, source_item_id: SourceItemId) -> TreeArc<SyntaxNode>; | 52 | fn file_item(&self, source_item_id: SourceItemId) -> TreeArc<SyntaxNode>; |
52 | 53 | ||
53 | #[salsa::invoke(crate::module_tree::Submodule::submodules_query)] | 54 | #[salsa::invoke(crate::module_tree::Submodule::submodules_query)] |
54 | fn submodules(&self, source: SourceItemId) -> Arc<Vec<crate::module_tree::Submodule>>; | 55 | fn submodules( |
56 | &self, | ||
57 | file_id: HirFileId, | ||
58 | delc_id: Option<SourceFileItemId>, | ||
59 | ) -> Arc<Vec<crate::module_tree::Submodule>>; | ||
55 | 60 | ||
56 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_query)] | 61 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_query)] |
57 | fn lower_module(&self, module: Module) -> (Arc<LoweredModule>, Arc<ImportSourceMap>); | 62 | fn lower_module(&self, module: Module) -> (Arc<LoweredModule>, Arc<ImportSourceMap>); |
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 7dd4b540e..0e4dc6261 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -4,7 +4,7 @@ use std::{ | |||
4 | }; | 4 | }; |
5 | 5 | ||
6 | use ra_db::{LocationIntener, FileId}; | 6 | use ra_db::{LocationIntener, FileId}; |
7 | use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; | 7 | use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, SyntaxNodePtr, ast}; |
8 | use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; | 8 | use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
@@ -203,7 +203,7 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone { | |||
203 | let items = ctx.db.file_items(ctx.file_id); | 203 | let items = ctx.db.file_items(ctx.file_id); |
204 | let raw = SourceItemId { | 204 | let raw = SourceItemId { |
205 | file_id: ctx.file_id, | 205 | file_id: ctx.file_id, |
206 | item_id: Some(items.id_of(ctx.file_id, ast.syntax())), | 206 | item_id: items.id_of(ctx.file_id, ast.syntax()), |
207 | }; | 207 | }; |
208 | let loc = ItemLoc { | 208 | let loc = ItemLoc { |
209 | module: ctx.module, | 209 | module: ctx.module, |
@@ -301,15 +301,14 @@ impl_arena_id!(SourceFileItemId); | |||
301 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 301 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
302 | pub struct SourceItemId { | 302 | pub struct SourceItemId { |
303 | pub(crate) file_id: HirFileId, | 303 | pub(crate) file_id: HirFileId, |
304 | /// None for the whole file. | 304 | pub(crate) item_id: SourceFileItemId, |
305 | pub(crate) item_id: Option<SourceFileItemId>, | ||
306 | } | 305 | } |
307 | 306 | ||
308 | /// Maps items' `SyntaxNode`s to `SourceFileItemId`s and back. | 307 | /// Maps items' `SyntaxNode`s to `SourceFileItemId`s and back. |
309 | #[derive(Debug, PartialEq, Eq)] | 308 | #[derive(Debug, PartialEq, Eq)] |
310 | pub struct SourceFileItems { | 309 | pub struct SourceFileItems { |
311 | file_id: HirFileId, | 310 | file_id: HirFileId, |
312 | arena: Arena<SourceFileItemId, TreeArc<SyntaxNode>>, | 311 | arena: Arena<SourceFileItemId, SyntaxNodePtr>, |
313 | } | 312 | } |
314 | 313 | ||
315 | impl SourceFileItems { | 314 | impl SourceFileItems { |
@@ -329,15 +328,15 @@ impl SourceFileItems { | |||
329 | // trait does not chage ids of top-level items, which helps caching. | 328 | // trait does not chage ids of top-level items, which helps caching. |
330 | bfs(source_file.syntax(), |it| { | 329 | bfs(source_file.syntax(), |it| { |
331 | if let Some(module_item) = ast::ModuleItem::cast(it) { | 330 | if let Some(module_item) = ast::ModuleItem::cast(it) { |
332 | self.alloc(module_item.syntax().to_owned()); | 331 | self.alloc(module_item.syntax()); |
333 | } else if let Some(macro_call) = ast::MacroCall::cast(it) { | 332 | } else if let Some(macro_call) = ast::MacroCall::cast(it) { |
334 | self.alloc(macro_call.syntax().to_owned()); | 333 | self.alloc(macro_call.syntax()); |
335 | } | 334 | } |
336 | }) | 335 | }) |
337 | } | 336 | } |
338 | 337 | ||
339 | fn alloc(&mut self, item: TreeArc<SyntaxNode>) -> SourceFileItemId { | 338 | fn alloc(&mut self, item: &SyntaxNode) -> SourceFileItemId { |
340 | self.arena.alloc(item) | 339 | self.arena.alloc(SyntaxNodePtr::new(item)) |
341 | } | 340 | } |
342 | pub(crate) fn id_of(&self, file_id: HirFileId, item: &SyntaxNode) -> SourceFileItemId { | 341 | pub(crate) fn id_of(&self, file_id: HirFileId, item: &SyntaxNode) -> SourceFileItemId { |
343 | assert_eq!( | 342 | assert_eq!( |
@@ -348,17 +347,8 @@ impl SourceFileItems { | |||
348 | self.id_of_unchecked(item) | 347 | self.id_of_unchecked(item) |
349 | } | 348 | } |
350 | pub(crate) fn id_of_unchecked(&self, item: &SyntaxNode) -> SourceFileItemId { | 349 | pub(crate) fn id_of_unchecked(&self, item: &SyntaxNode) -> SourceFileItemId { |
351 | if let Some((id, _)) = self.arena.iter().find(|(_id, i)| *i == item) { | 350 | let ptr = SyntaxNodePtr::new(item); |
352 | return id; | 351 | if let Some((id, _)) = self.arena.iter().find(|(_id, i)| **i == ptr) { |
353 | } | ||
354 | // This should not happen. Let's try to give a sensible diagnostics. | ||
355 | if let Some((id, i)) = self.arena.iter().find(|(_id, i)| i.range() == item.range()) { | ||
356 | // FIXME(#288): whyyy are we getting here? | ||
357 | log::error!( | ||
358 | "unequal syntax nodes with the same range:\n{:?}\n{:?}", | ||
359 | item, | ||
360 | i | ||
361 | ); | ||
362 | return id; | 352 | return id; |
363 | } | 353 | } |
364 | panic!( | 354 | panic!( |
@@ -367,15 +357,11 @@ impl SourceFileItems { | |||
367 | self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(), | 357 | self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(), |
368 | ); | 358 | ); |
369 | } | 359 | } |
370 | pub fn id_of_parse(&self) -> SourceFileItemId { | ||
371 | let (id, _syntax) = self.arena.iter().next().unwrap(); | ||
372 | id | ||
373 | } | ||
374 | } | 360 | } |
375 | 361 | ||
376 | impl std::ops::Index<SourceFileItemId> for SourceFileItems { | 362 | impl std::ops::Index<SourceFileItemId> for SourceFileItems { |
377 | type Output = SyntaxNode; | 363 | type Output = SyntaxNodePtr; |
378 | fn index(&self, idx: SourceFileItemId) -> &SyntaxNode { | 364 | fn index(&self, idx: SourceFileItemId) -> &SyntaxNodePtr { |
379 | &self.arena[idx] | 365 | &self.arena[idx] |
380 | } | 366 | } |
381 | } | 367 | } |
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs index d5ad9decb..d1dc3fa4b 100644 --- a/crates/ra_hir/src/module_tree.rs +++ b/crates/ra_hir/src/module_tree.rs | |||
@@ -11,21 +11,28 @@ use ra_syntax::{ | |||
11 | use ra_arena::{Arena, RawId, impl_arena_id}; | 11 | use ra_arena::{Arena, RawId, impl_arena_id}; |
12 | use test_utils::tested_by; | 12 | use test_utils::tested_by; |
13 | 13 | ||
14 | use crate::{Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource}; | 14 | use crate::{ |
15 | Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource, | ||
16 | ids::SourceFileItemId, | ||
17 | }; | ||
15 | 18 | ||
16 | impl ModuleSource { | 19 | impl ModuleSource { |
17 | pub(crate) fn from_source_item_id( | 20 | pub(crate) fn new( |
18 | db: &impl HirDatabase, | 21 | db: &impl HirDatabase, |
19 | source_item_id: SourceItemId, | 22 | file_id: HirFileId, |
23 | decl_id: Option<SourceFileItemId>, | ||
20 | ) -> ModuleSource { | 24 | ) -> ModuleSource { |
21 | let module_syntax = db.file_item(source_item_id); | 25 | match decl_id { |
22 | if let Some(source_file) = ast::SourceFile::cast(&module_syntax) { | 26 | Some(item_id) => { |
23 | ModuleSource::SourceFile(source_file.to_owned()) | 27 | let module = db.file_item(SourceItemId { file_id, item_id }); |
24 | } else if let Some(module) = ast::Module::cast(&module_syntax) { | 28 | let module = ast::Module::cast(&*module).unwrap(); |
25 | assert!(module.item_list().is_some(), "expected inline module"); | 29 | assert!(module.item_list().is_some(), "expected inline module"); |
26 | ModuleSource::Module(module.to_owned()) | 30 | ModuleSource::Module(module.to_owned()) |
27 | } else { | 31 | } |
28 | panic!("expected file or inline module") | 32 | None => { |
33 | let source_file = db.hir_parse(file_id); | ||
34 | ModuleSource::SourceFile(source_file) | ||
35 | } | ||
29 | } | 36 | } |
30 | } | 37 | } |
31 | } | 38 | } |
@@ -34,18 +41,18 @@ impl ModuleSource { | |||
34 | pub struct Submodule { | 41 | pub struct Submodule { |
35 | name: Name, | 42 | name: Name, |
36 | is_declaration: bool, | 43 | is_declaration: bool, |
37 | source: SourceItemId, | 44 | decl_id: SourceFileItemId, |
38 | } | 45 | } |
39 | 46 | ||
40 | impl Submodule { | 47 | impl Submodule { |
41 | pub(crate) fn submodules_query( | 48 | pub(crate) fn submodules_query( |
42 | db: &impl HirDatabase, | 49 | db: &impl HirDatabase, |
43 | source: SourceItemId, | 50 | file_id: HirFileId, |
51 | decl_id: Option<SourceFileItemId>, | ||
44 | ) -> Arc<Vec<Submodule>> { | 52 | ) -> Arc<Vec<Submodule>> { |
45 | db.check_canceled(); | 53 | db.check_canceled(); |
46 | let file_id = source.file_id; | ||
47 | let file_items = db.file_items(file_id); | 54 | let file_items = db.file_items(file_id); |
48 | let module_source = ModuleSource::from_source_item_id(db, source); | 55 | let module_source = ModuleSource::new(db, file_id, decl_id); |
49 | let submodules = match module_source { | 56 | let submodules = match module_source { |
50 | ModuleSource::SourceFile(source_file) => { | 57 | ModuleSource::SourceFile(source_file) => { |
51 | collect_submodules(file_id, &file_items, &*source_file) | 58 | collect_submodules(file_id, &file_items, &*source_file) |
@@ -54,6 +61,7 @@ impl Submodule { | |||
54 | collect_submodules(file_id, &file_items, module.item_list().unwrap()) | 61 | collect_submodules(file_id, &file_items, module.item_list().unwrap()) |
55 | } | 62 | } |
56 | }; | 63 | }; |
64 | |||
57 | return Arc::new(submodules); | 65 | return Arc::new(submodules); |
58 | 66 | ||
59 | fn collect_submodules( | 67 | fn collect_submodules( |
@@ -75,10 +83,7 @@ impl Submodule { | |||
75 | let sub = Submodule { | 83 | let sub = Submodule { |
76 | name, | 84 | name, |
77 | is_declaration: module.has_semi(), | 85 | is_declaration: module.has_semi(), |
78 | source: SourceItemId { | 86 | decl_id: file_items.id_of(file_id, module.syntax()), |
79 | file_id, | ||
80 | item_id: Some(file_items.id_of(file_id, module.syntax())), | ||
81 | }, | ||
82 | }; | 87 | }; |
83 | Some(sub) | 88 | Some(sub) |
84 | }) | 89 | }) |
@@ -110,7 +115,9 @@ pub struct ModuleTree { | |||
110 | 115 | ||
111 | #[derive(Debug, PartialEq, Eq, Hash)] | 116 | #[derive(Debug, PartialEq, Eq, Hash)] |
112 | pub struct ModuleData { | 117 | pub struct ModuleData { |
113 | source: SourceItemId, | 118 | file_id: HirFileId, |
119 | /// Points to `ast::Module`, `None` for the whole file. | ||
120 | decl_id: Option<SourceFileItemId>, | ||
114 | parent: Option<LinkId>, | 121 | parent: Option<LinkId>, |
115 | children: Vec<LinkId>, | 122 | children: Vec<LinkId>, |
116 | } | 123 | } |
@@ -136,8 +143,15 @@ impl ModuleTree { | |||
136 | self.mods.iter().map(|(id, _)| id) | 143 | self.mods.iter().map(|(id, _)| id) |
137 | } | 144 | } |
138 | 145 | ||
139 | pub(crate) fn find_module_by_source(&self, source: SourceItemId) -> Option<ModuleId> { | 146 | pub(crate) fn find_module_by_source( |
140 | let (res, _) = self.mods.iter().find(|(_, m)| m.source == source)?; | 147 | &self, |
148 | file_id: HirFileId, | ||
149 | decl_id: Option<SourceFileItemId>, | ||
150 | ) -> Option<ModuleId> { | ||
151 | let (res, _) = self | ||
152 | .mods | ||
153 | .iter() | ||
154 | .find(|(_, m)| (m.file_id, m.decl_id) == (file_id, decl_id))?; | ||
141 | Some(res) | 155 | Some(res) |
142 | } | 156 | } |
143 | 157 | ||
@@ -147,11 +161,7 @@ impl ModuleTree { | |||
147 | let source_root_id = db.file_source_root(file_id); | 161 | let source_root_id = db.file_source_root(file_id); |
148 | 162 | ||
149 | let source_root = db.source_root(source_root_id); | 163 | let source_root = db.source_root(source_root_id); |
150 | let source = SourceItemId { | 164 | self.init_subtree(db, &source_root, None, file_id.into(), None); |
151 | file_id: file_id.into(), | ||
152 | item_id: None, | ||
153 | }; | ||
154 | self.init_subtree(db, &source_root, None, source); | ||
155 | } | 165 | } |
156 | 166 | ||
157 | fn init_subtree( | 167 | fn init_subtree( |
@@ -159,16 +169,21 @@ impl ModuleTree { | |||
159 | db: &impl HirDatabase, | 169 | db: &impl HirDatabase, |
160 | source_root: &SourceRoot, | 170 | source_root: &SourceRoot, |
161 | parent: Option<LinkId>, | 171 | parent: Option<LinkId>, |
162 | source: SourceItemId, | 172 | file_id: HirFileId, |
173 | decl_id: Option<SourceFileItemId>, | ||
163 | ) -> ModuleId { | 174 | ) -> ModuleId { |
164 | let id = self.alloc_mod(ModuleData { | 175 | let id = self.alloc_mod(ModuleData { |
165 | source, | 176 | file_id, |
177 | decl_id, | ||
166 | parent, | 178 | parent, |
167 | children: Vec::new(), | 179 | children: Vec::new(), |
168 | }); | 180 | }); |
169 | for sub in db.submodules(source).iter() { | 181 | for sub in db.submodules(file_id, decl_id).iter() { |
170 | let link = self.alloc_link(LinkData { | 182 | let link = self.alloc_link(LinkData { |
171 | source: sub.source, | 183 | source: SourceItemId { |
184 | file_id, | ||
185 | item_id: sub.decl_id, | ||
186 | }, | ||
172 | name: sub.name.clone(), | 187 | name: sub.name.clone(), |
173 | owner: id, | 188 | owner: id, |
174 | points_to: Vec::new(), | 189 | points_to: Vec::new(), |
@@ -176,24 +191,17 @@ impl ModuleTree { | |||
176 | }); | 191 | }); |
177 | 192 | ||
178 | let (points_to, problem) = if sub.is_declaration { | 193 | let (points_to, problem) = if sub.is_declaration { |
179 | let (points_to, problem) = resolve_submodule(db, source.file_id, &sub.name); | 194 | let (points_to, problem) = resolve_submodule(db, file_id, &sub.name); |
180 | let points_to = points_to | 195 | let points_to = points_to |
181 | .into_iter() | 196 | .into_iter() |
182 | .map(|file_id| { | 197 | .map(|file_id| { |
183 | self.init_subtree( | 198 | self.init_subtree(db, source_root, Some(link), file_id.into(), None) |
184 | db, | ||
185 | source_root, | ||
186 | Some(link), | ||
187 | SourceItemId { | ||
188 | file_id: file_id.into(), | ||
189 | item_id: None, | ||
190 | }, | ||
191 | ) | ||
192 | }) | 199 | }) |
193 | .collect::<Vec<_>>(); | 200 | .collect::<Vec<_>>(); |
194 | (points_to, problem) | 201 | (points_to, problem) |
195 | } else { | 202 | } else { |
196 | let points_to = self.init_subtree(db, source_root, Some(link), sub.source); | 203 | let points_to = |
204 | self.init_subtree(db, source_root, Some(link), file_id, Some(sub.decl_id)); | ||
197 | (vec![points_to], None) | 205 | (vec![points_to], None) |
198 | }; | 206 | }; |
199 | 207 | ||
@@ -216,8 +224,11 @@ impl ModuleTree { | |||
216 | } | 224 | } |
217 | 225 | ||
218 | impl ModuleId { | 226 | impl ModuleId { |
219 | pub(crate) fn source(self, tree: &ModuleTree) -> SourceItemId { | 227 | pub(crate) fn file_id(self, tree: &ModuleTree) -> HirFileId { |
220 | tree.mods[self].source | 228 | tree.mods[self].file_id |
229 | } | ||
230 | pub(crate) fn decl_id(self, tree: &ModuleTree) -> Option<SourceFileItemId> { | ||
231 | tree.mods[self].decl_id | ||
221 | } | 232 | } |
222 | pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { | 233 | pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { |
223 | tree.mods[self].parent | 234 | tree.mods[self].parent |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 5193900e0..97ce6c946 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -215,7 +215,7 @@ where | |||
215 | // Populate extern crates prelude | 215 | // Populate extern crates prelude |
216 | { | 216 | { |
217 | let root_id = module_id.crate_root(&self.module_tree); | 217 | let root_id = module_id.crate_root(&self.module_tree); |
218 | let file_id = root_id.source(&self.module_tree).file_id; | 218 | let file_id = root_id.file_id(&self.module_tree); |
219 | let crate_graph = self.db.crate_graph(); | 219 | let crate_graph = self.db.crate_graph(); |
220 | if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file()) | 220 | if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file()) |
221 | { | 221 | { |
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 1d77548f3..8df11a5f4 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -121,10 +121,7 @@ impl LoweredModule { | |||
121 | let item_id = file_items.id_of_unchecked(macro_call.syntax()); | 121 | let item_id = file_items.id_of_unchecked(macro_call.syntax()); |
122 | let loc = MacroCallLoc { | 122 | let loc = MacroCallLoc { |
123 | module, | 123 | module, |
124 | source_item_id: SourceItemId { | 124 | source_item_id: SourceItemId { file_id, item_id }, |
125 | file_id, | ||
126 | item_id: Some(item_id), | ||
127 | }, | ||
128 | }; | 125 | }; |
129 | let id = loc.id(db); | 126 | let id = loc.id(db); |
130 | let file_id = HirFileId::from(id); | 127 | let file_id = HirFileId::from(id); |
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index 61c93a964..bf9ac0dfb 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs | |||
@@ -4,9 +4,7 @@ use std::{ | |||
4 | }; | 4 | }; |
5 | 5 | ||
6 | use rustc_hash::FxHashMap; | 6 | use rustc_hash::FxHashMap; |
7 | use ra_syntax::{ | 7 | use ra_syntax::{SyntaxNode, TreeArc}; |
8 | AstNode, SyntaxNode, TreeArc, | ||
9 | }; | ||
10 | use ra_db::{CrateId}; | 8 | use ra_db::{CrateId}; |
11 | 9 | ||
12 | use crate::{ | 10 | use crate::{ |
@@ -32,10 +30,10 @@ pub(super) fn file_item( | |||
32 | db: &impl HirDatabase, | 30 | db: &impl HirDatabase, |
33 | source_item_id: SourceItemId, | 31 | source_item_id: SourceItemId, |
34 | ) -> TreeArc<SyntaxNode> { | 32 | ) -> TreeArc<SyntaxNode> { |
35 | match source_item_id.item_id { | 33 | let source_file = db.hir_parse(source_item_id.file_id); |
36 | Some(id) => db.file_items(source_item_id.file_id)[id].to_owned(), | 34 | db.file_items(source_item_id.file_id)[source_item_id.item_id] |
37 | None => db.hir_parse(source_item_id.file_id).syntax().to_owned(), | 35 | .to_node(&source_file) |
38 | } | 36 | .to_owned() |
39 | } | 37 | } |
40 | 38 | ||
41 | pub(super) fn item_map(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ItemMap> { | 39 | pub(super) fn item_map(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ItemMap> { |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index c0b3f1cd4..f523f0647 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -13,18 +13,14 @@ use ra_syntax::{ | |||
13 | }; | 13 | }; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | HirDatabase, Function, SourceItemId, ModuleDef, | 16 | HirDatabase, Function, ModuleDef, |
17 | AsName, Module, | 17 | AsName, Module, HirFileId, |
18 | ids::LocationCtx, | 18 | ids::{LocationCtx, SourceFileItemId}, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | /// Locates the module by `FileId`. Picks topmost module in the file. | 21 | /// Locates the module by `FileId`. Picks topmost module in the file. |
22 | pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Option<Module> { | 22 | pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Option<Module> { |
23 | let module_source = SourceItemId { | 23 | module_from_source(db, file_id.into(), None) |
24 | file_id: file_id.into(), | ||
25 | item_id: None, | ||
26 | }; | ||
27 | module_from_source(db, module_source) | ||
28 | } | 24 | } |
29 | 25 | ||
30 | /// Locates the child module by `mod child;` declaration. | 26 | /// Locates the child module by `mod child;` declaration. |
@@ -59,11 +55,7 @@ fn module_from_inline( | |||
59 | let file_id = file_id.into(); | 55 | let file_id = file_id.into(); |
60 | let file_items = db.file_items(file_id); | 56 | let file_items = db.file_items(file_id); |
61 | let item_id = file_items.id_of(file_id, module.syntax()); | 57 | let item_id = file_items.id_of(file_id, module.syntax()); |
62 | let source = SourceItemId { | 58 | module_from_source(db, file_id, Some(item_id)) |
63 | file_id, | ||
64 | item_id: Some(item_id), | ||
65 | }; | ||
66 | module_from_source(db, source) | ||
67 | } | 59 | } |
68 | 60 | ||
69 | /// Locates the module by child syntax element within the module | 61 | /// Locates the module by child syntax element within the module |
@@ -83,13 +75,17 @@ pub fn module_from_child_node( | |||
83 | } | 75 | } |
84 | } | 76 | } |
85 | 77 | ||
86 | fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Option<Module> { | 78 | fn module_from_source( |
87 | let source_root_id = db.file_source_root(source.file_id.as_original_file()); | 79 | db: &impl HirDatabase, |
80 | file_id: HirFileId, | ||
81 | decl_id: Option<SourceFileItemId>, | ||
82 | ) -> Option<Module> { | ||
83 | let source_root_id = db.file_source_root(file_id.as_original_file()); | ||
88 | db.source_root_crates(source_root_id) | 84 | db.source_root_crates(source_root_id) |
89 | .iter() | 85 | .iter() |
90 | .find_map(|&krate| { | 86 | .find_map(|&krate| { |
91 | let module_tree = db.module_tree(krate); | 87 | let module_tree = db.module_tree(krate); |
92 | let module_id = module_tree.find_module_by_source(source)?; | 88 | let module_id = module_tree.find_module_by_source(file_id, decl_id)?; |
93 | Some(Module { krate, module_id }) | 89 | Some(Module { krate, module_id }) |
94 | }) | 90 | }) |
95 | } | 91 | } |
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs index 3267fff96..f203a6bf1 100644 --- a/crates/ra_ide_api/src/call_info.rs +++ b/crates/ra_ide_api/src/call_info.rs | |||
@@ -1,3 +1,4 @@ | |||
1 | use test_utils::tested_by; | ||
1 | use ra_db::SourceDatabase; | 2 | use ra_db::SourceDatabase; |
2 | use ra_syntax::{ | 3 | use ra_syntax::{ |
3 | AstNode, SyntaxNode, TextUnit, TextRange, | 4 | AstNode, SyntaxNode, TextUnit, TextRange, |
@@ -41,7 +42,12 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
41 | // where offset is in that list (or beyond). | 42 | // where offset is in that list (or beyond). |
42 | // Revisit this after we get documentation comments in. | 43 | // Revisit this after we get documentation comments in. |
43 | if let Some(ref arg_list) = calling_node.arg_list() { | 44 | if let Some(ref arg_list) = calling_node.arg_list() { |
44 | let start = arg_list.syntax().range().start(); | 45 | let arg_list_range = arg_list.syntax().range(); |
46 | if !arg_list_range.contains_inclusive(position.offset) { | ||
47 | tested_by!(call_info_bad_offset); | ||
48 | return None; | ||
49 | } | ||
50 | let start = arg_list_range.start(); | ||
45 | 51 | ||
46 | let range_search = TextRange::from_to(start, position.offset); | 52 | let range_search = TextRange::from_to(start, position.offset); |
47 | let mut commas: usize = arg_list | 53 | let mut commas: usize = arg_list |
@@ -172,10 +178,12 @@ fn param_list(node: &ast::FnDef) -> Vec<String> { | |||
172 | 178 | ||
173 | #[cfg(test)] | 179 | #[cfg(test)] |
174 | mod tests { | 180 | mod tests { |
175 | use super::*; | 181 | use test_utils::covers; |
176 | 182 | ||
177 | use crate::mock_analysis::single_file_with_position; | 183 | use crate::mock_analysis::single_file_with_position; |
178 | 184 | ||
185 | use super::*; | ||
186 | |||
179 | fn call_info(text: &str) -> CallInfo { | 187 | fn call_info(text: &str) -> CallInfo { |
180 | let (analysis, position) = single_file_with_position(text); | 188 | let (analysis, position) = single_file_with_position(text); |
181 | analysis.call_info(position).unwrap().unwrap() | 189 | analysis.call_info(position).unwrap().unwrap() |
@@ -417,4 +425,14 @@ By default this method stops actor's `Context`."# | |||
417 | ); | 425 | ); |
418 | } | 426 | } |
419 | 427 | ||
428 | #[test] | ||
429 | fn call_info_bad_offset() { | ||
430 | covers!(call_info_bad_offset); | ||
431 | let (analysis, position) = single_file_with_position( | ||
432 | r#"fn foo(x: u32, y: u32) -> u32 {x + y} | ||
433 | fn bar() { foo <|> (3, ); }"#, | ||
434 | ); | ||
435 | let call_info = analysis.call_info(position).unwrap(); | ||
436 | assert!(call_info.is_none()); | ||
437 | } | ||
420 | } | 438 | } |
diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide_api/src/marks.rs index e33bf6c91..21ce7289d 100644 --- a/crates/ra_ide_api/src/marks.rs +++ b/crates/ra_ide_api/src/marks.rs | |||
@@ -2,4 +2,5 @@ test_utils::marks!( | |||
2 | inserts_parens_for_function_calls | 2 | inserts_parens_for_function_calls |
3 | goto_definition_works_for_methods | 3 | goto_definition_works_for_methods |
4 | goto_definition_works_for_fields | 4 | goto_definition_works_for_fields |
5 | call_info_bad_offset | ||
5 | ); | 6 | ); |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 8ea9edc84..ace3da020 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -520,21 +520,33 @@ pub fn handle_formatting( | |||
520 | let end_position = TextUnit::of_str(&file).conv_with(&file_line_index); | 520 | let end_position = TextUnit::of_str(&file).conv_with(&file_line_index); |
521 | 521 | ||
522 | use std::process; | 522 | use std::process; |
523 | let mut rustfmt = process::Command::new("rustfmt") | 523 | let mut rustfmt = process::Command::new("rustfmt"); |
524 | rustfmt | ||
524 | .stdin(process::Stdio::piped()) | 525 | .stdin(process::Stdio::piped()) |
525 | .stdout(process::Stdio::piped()) | 526 | .stdout(process::Stdio::piped()); |
526 | .spawn()?; | 527 | |
528 | if let Ok(path) = params.text_document.uri.to_file_path() { | ||
529 | if let Some(parent) = path.parent() { | ||
530 | rustfmt.current_dir(parent); | ||
531 | } | ||
532 | } | ||
533 | let mut rustfmt = rustfmt.spawn()?; | ||
527 | 534 | ||
528 | rustfmt.stdin.as_mut().unwrap().write_all(file.as_bytes())?; | 535 | rustfmt.stdin.as_mut().unwrap().write_all(file.as_bytes())?; |
529 | 536 | ||
530 | let output = rustfmt.wait_with_output()?; | 537 | let output = rustfmt.wait_with_output()?; |
531 | let captured_stdout = String::from_utf8(output.stdout)?; | 538 | let captured_stdout = String::from_utf8(output.stdout)?; |
532 | if !output.status.success() { | 539 | if !output.status.success() { |
533 | failure::bail!( | 540 | return Err(LspError::new( |
534 | "rustfmt exited with error code {}: {}.", | 541 | -32900, |
535 | output.status, | 542 | format!( |
536 | captured_stdout, | 543 | r#"rustfmt exited with: |
537 | ); | 544 | Status: {} |
545 | stdout: {}"#, | ||
546 | output.status, captured_stdout, | ||
547 | ), | ||
548 | ) | ||
549 | .into()); | ||
538 | } | 550 | } |
539 | 551 | ||
540 | Ok(Some(vec![TextEdit { | 552 | Ok(Some(vec![TextEdit { |
diff --git a/crates/ra_lsp_server/src/project_model/cargo_workspace.rs b/crates/ra_lsp_server/src/project_model/cargo_workspace.rs index 75ae78bca..8cf99d586 100644 --- a/crates/ra_lsp_server/src/project_model/cargo_workspace.rs +++ b/crates/ra_lsp_server/src/project_model/cargo_workspace.rs | |||
@@ -117,9 +117,13 @@ impl Target { | |||
117 | 117 | ||
118 | impl CargoWorkspace { | 118 | impl CargoWorkspace { |
119 | pub fn from_cargo_metadata(cargo_toml: &Path) -> Result<CargoWorkspace> { | 119 | pub fn from_cargo_metadata(cargo_toml: &Path) -> Result<CargoWorkspace> { |
120 | let meta = MetadataCommand::new() | 120 | let mut meta = MetadataCommand::new(); |
121 | .manifest_path(cargo_toml) | 121 | meta.manifest_path(cargo_toml) |
122 | .features(CargoOpt::AllFeatures) | 122 | .features(CargoOpt::AllFeatures); |
123 | if let Some(parent) = cargo_toml.parent() { | ||
124 | meta.current_dir(parent); | ||
125 | } | ||
126 | let meta = meta | ||
123 | .exec() | 127 | .exec() |
124 | .map_err(|e| format_err!("cargo metadata failed: {}", e))?; | 128 | .map_err(|e| format_err!("cargo metadata failed: {}", e))?; |
125 | let mut pkg_by_id = FxHashMap::default(); | 129 | let mut pkg_by_id = FxHashMap::default(); |