diff options
-rw-r--r-- | Cargo.lock | 6 | ||||
-rw-r--r-- | crates/ra_db/Cargo.toml | 2 | ||||
-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_syntax/src/grammar/expressions.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.rs | 8 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.txt | 109 |
13 files changed, 219 insertions, 109 deletions
diff --git a/Cargo.lock b/Cargo.lock index b3fa7354d..dc54edef6 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -1061,7 +1061,7 @@ version = "0.1.1" | |||
1061 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1061 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1062 | dependencies = [ | 1062 | dependencies = [ |
1063 | "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | 1063 | "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", |
1064 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1064 | "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", |
1065 | ] | 1065 | ] |
1066 | 1066 | ||
1067 | [[package]] | 1067 | [[package]] |
@@ -1090,7 +1090,7 @@ name = "rand_hc" | |||
1090 | version = "0.1.0" | 1090 | version = "0.1.0" |
1091 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1092 | dependencies = [ | 1092 | dependencies = [ |
1093 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1093 | "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", |
1094 | ] | 1094 | ] |
1095 | 1095 | ||
1096 | [[package]] | 1096 | [[package]] |
@@ -1128,7 +1128,7 @@ name = "rand_xorshift" | |||
1128 | version = "0.1.1" | 1128 | version = "0.1.1" |
1129 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1129 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1130 | dependencies = [ | 1130 | dependencies = [ |
1131 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1131 | "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", |
1132 | ] | 1132 | ] |
1133 | 1133 | ||
1134 | [[package]] | 1134 | [[package]] |
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml index 9aa77f72e..2d39b77ed 100644 --- a/crates/ra_db/Cargo.toml +++ b/crates/ra_db/Cargo.toml | |||
@@ -6,7 +6,7 @@ authors = ["Aleksey Kladov <[email protected]>"] | |||
6 | 6 | ||
7 | [dependencies] | 7 | [dependencies] |
8 | relative-path = "0.4.0" | 8 | relative-path = "0.4.0" |
9 | salsa = "0.10.0-alpha4" | 9 | salsa = "0.10.0-alpha5" |
10 | rustc-hash = "1.0" | 10 | rustc-hash = "1.0" |
11 | parking_lot = "0.7.0" | 11 | parking_lot = "0.7.0" |
12 | 12 | ||
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_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs index 7ee32fa7c..1604d9b5a 100644 --- a/crates/ra_syntax/src/grammar/expressions.rs +++ b/crates/ra_syntax/src/grammar/expressions.rs | |||
@@ -423,7 +423,7 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) { | |||
423 | match p.current() { | 423 | match p.current() { |
424 | L_CURLY if !r.forbid_structs => { | 424 | L_CURLY if !r.forbid_structs => { |
425 | named_field_list(p); | 425 | named_field_list(p); |
426 | (m.complete(p, STRUCT_LIT), BlockLike::Block) | 426 | (m.complete(p, STRUCT_LIT), BlockLike::NotBlock) |
427 | } | 427 | } |
428 | EXCL => { | 428 | EXCL => { |
429 | let block_like = items::macro_call_after_excl(p); | 429 | let block_like = items::macro_call_after_excl(p); |
diff --git a/crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.rs b/crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.rs new file mode 100644 index 000000000..7e4a28bf7 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.rs | |||
@@ -0,0 +1,8 @@ | |||
1 | // https://github.com/rust-analyzer/rust-analyzer/issues/674 | ||
2 | |||
3 | struct Repr { raw: [u8; 1] } | ||
4 | |||
5 | fn abc() { | ||
6 | Repr { raw: [0] }.raw[0] = 0; | ||
7 | Repr{raw:[0]}(); | ||
8 | } | ||
diff --git a/crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.txt b/crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.txt new file mode 100644 index 000000000..2279c7966 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.txt | |||
@@ -0,0 +1,109 @@ | |||
1 | SOURCE_FILE@[0; 160) | ||
2 | COMMENT@[0; 60) | ||
3 | WHITESPACE@[60; 62) | ||
4 | STRUCT_DEF@[62; 90) | ||
5 | STRUCT_KW@[62; 68) | ||
6 | WHITESPACE@[68; 69) | ||
7 | NAME@[69; 73) | ||
8 | IDENT@[69; 73) "Repr" | ||
9 | WHITESPACE@[73; 74) | ||
10 | NAMED_FIELD_DEF_LIST@[74; 90) | ||
11 | L_CURLY@[74; 75) | ||
12 | WHITESPACE@[75; 76) | ||
13 | NAMED_FIELD_DEF@[76; 88) | ||
14 | NAME@[76; 79) | ||
15 | IDENT@[76; 79) "raw" | ||
16 | COLON@[79; 80) | ||
17 | WHITESPACE@[80; 81) | ||
18 | ARRAY_TYPE@[81; 88) | ||
19 | L_BRACK@[81; 82) | ||
20 | PATH_TYPE@[82; 84) | ||
21 | PATH@[82; 84) | ||
22 | PATH_SEGMENT@[82; 84) | ||
23 | NAME_REF@[82; 84) | ||
24 | IDENT@[82; 84) "u8" | ||
25 | SEMI@[84; 85) | ||
26 | WHITESPACE@[85; 86) | ||
27 | LITERAL@[86; 87) | ||
28 | INT_NUMBER@[86; 87) "1" | ||
29 | R_BRACK@[87; 88) | ||
30 | WHITESPACE@[88; 89) | ||
31 | R_CURLY@[89; 90) | ||
32 | WHITESPACE@[90; 92) | ||
33 | FN_DEF@[92; 159) | ||
34 | FN_KW@[92; 94) | ||
35 | WHITESPACE@[94; 95) | ||
36 | NAME@[95; 98) | ||
37 | IDENT@[95; 98) "abc" | ||
38 | PARAM_LIST@[98; 100) | ||
39 | L_PAREN@[98; 99) | ||
40 | R_PAREN@[99; 100) | ||
41 | WHITESPACE@[100; 101) | ||
42 | BLOCK@[101; 159) | ||
43 | L_CURLY@[101; 102) | ||
44 | WHITESPACE@[102; 107) | ||
45 | EXPR_STMT@[107; 136) | ||
46 | BIN_EXPR@[107; 135) | ||
47 | INDEX_EXPR@[107; 131) | ||
48 | FIELD_EXPR@[107; 128) | ||
49 | STRUCT_LIT@[107; 124) | ||
50 | PATH@[107; 111) | ||
51 | PATH_SEGMENT@[107; 111) | ||
52 | NAME_REF@[107; 111) | ||
53 | IDENT@[107; 111) "Repr" | ||
54 | WHITESPACE@[111; 112) | ||
55 | NAMED_FIELD_LIST@[112; 124) | ||
56 | L_CURLY@[112; 113) | ||
57 | WHITESPACE@[113; 114) | ||
58 | NAMED_FIELD@[114; 122) | ||
59 | NAME_REF@[114; 117) | ||
60 | IDENT@[114; 117) "raw" | ||
61 | COLON@[117; 118) | ||
62 | WHITESPACE@[118; 119) | ||
63 | ARRAY_EXPR@[119; 122) | ||
64 | L_BRACK@[119; 120) | ||
65 | LITERAL@[120; 121) | ||
66 | INT_NUMBER@[120; 121) "0" | ||
67 | R_BRACK@[121; 122) | ||
68 | WHITESPACE@[122; 123) | ||
69 | R_CURLY@[123; 124) | ||
70 | DOT@[124; 125) | ||
71 | NAME_REF@[125; 128) | ||
72 | IDENT@[125; 128) "raw" | ||
73 | L_BRACK@[128; 129) | ||
74 | LITERAL@[129; 130) | ||
75 | INT_NUMBER@[129; 130) "0" | ||
76 | R_BRACK@[130; 131) | ||
77 | WHITESPACE@[131; 132) | ||
78 | EQ@[132; 133) | ||
79 | WHITESPACE@[133; 134) | ||
80 | LITERAL@[134; 135) | ||
81 | INT_NUMBER@[134; 135) "0" | ||
82 | SEMI@[135; 136) | ||
83 | WHITESPACE@[136; 141) | ||
84 | EXPR_STMT@[141; 157) | ||
85 | CALL_EXPR@[141; 156) | ||
86 | STRUCT_LIT@[141; 154) | ||
87 | PATH@[141; 145) | ||
88 | PATH_SEGMENT@[141; 145) | ||
89 | NAME_REF@[141; 145) | ||
90 | IDENT@[141; 145) "Repr" | ||
91 | NAMED_FIELD_LIST@[145; 154) | ||
92 | L_CURLY@[145; 146) | ||
93 | NAMED_FIELD@[146; 153) | ||
94 | NAME_REF@[146; 149) | ||
95 | IDENT@[146; 149) "raw" | ||
96 | COLON@[149; 150) | ||
97 | ARRAY_EXPR@[150; 153) | ||
98 | L_BRACK@[150; 151) | ||
99 | LITERAL@[151; 152) | ||
100 | INT_NUMBER@[151; 152) "0" | ||
101 | R_BRACK@[152; 153) | ||
102 | R_CURLY@[153; 154) | ||
103 | ARG_LIST@[154; 156) | ||
104 | L_PAREN@[154; 155) | ||
105 | R_PAREN@[155; 156) | ||
106 | SEMI@[156; 157) | ||
107 | WHITESPACE@[157; 158) | ||
108 | R_CURLY@[158; 159) | ||
109 | WHITESPACE@[159; 160) | ||