aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/descriptors
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2018-11-27 12:03:14 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2018-11-27 12:03:14 +0000
commit0bc6f5802f3b80b76aeeb1668a1e1f5db7494309 (patch)
treeec9c94fa1bf857032b3914175d03fd179f74c660 /crates/ra_analysis/src/descriptors
parent8e37208040a456d4e481472f69b3b584655ee90f (diff)
parent10f4d4b74cd7e072bf5e8d3fb57c76f35ea03e1d (diff)
Merge #245
245: File items r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_analysis/src/descriptors')
-rw-r--r--crates/ra_analysis/src/descriptors/mod.rs18
-rw-r--r--crates/ra_analysis/src/descriptors/module/nameres.rs187
-rw-r--r--crates/ra_analysis/src/descriptors/path.rs19
3 files changed, 156 insertions, 68 deletions
diff --git a/crates/ra_analysis/src/descriptors/mod.rs b/crates/ra_analysis/src/descriptors/mod.rs
index 97750ea64..a5e956024 100644
--- a/crates/ra_analysis/src/descriptors/mod.rs
+++ b/crates/ra_analysis/src/descriptors/mod.rs
@@ -6,13 +6,14 @@ use std::sync::Arc;
6 6
7use ra_syntax::{ 7use ra_syntax::{
8 ast::{self, FnDefNode, AstNode}, 8 ast::{self, FnDefNode, AstNode},
9 TextRange, 9 TextRange, SyntaxNode,
10}; 10};
11 11
12use crate::{ 12use crate::{
13 FileId,
13 db::SyntaxDatabase, 14 db::SyntaxDatabase,
14 descriptors::function::{resolve_local_name, FnId, FnScopes}, 15 descriptors::function::{resolve_local_name, FnId, FnScopes},
15 descriptors::module::{ModuleId, ModuleTree, ModuleSource, nameres::{ItemMap, InputModuleItems}}, 16 descriptors::module::{ModuleId, ModuleTree, ModuleSource, nameres::{ItemMap, InputModuleItems, FileItems}},
16 input::SourceRootId, 17 input::SourceRootId,
17 loc2id::IdDatabase, 18 loc2id::IdDatabase,
18 syntax_ptr::LocalSyntaxPtr, 19 syntax_ptr::LocalSyntaxPtr,
@@ -20,6 +21,7 @@ use crate::{
20}; 21};
21 22
22pub(crate) use self::path::{Path, PathKind}; 23pub(crate) use self::path::{Path, PathKind};
24pub(crate) use self::module::nameres::FileItemId;
23 25
24salsa::query_group! { 26salsa::query_group! {
25 pub(crate) trait DescriptorDatabase: SyntaxDatabase + IdDatabase { 27 pub(crate) trait DescriptorDatabase: SyntaxDatabase + IdDatabase {
@@ -28,6 +30,18 @@ salsa::query_group! {
28 use fn function::imp::fn_scopes; 30 use fn function::imp::fn_scopes;
29 } 31 }
30 32
33 fn _file_items(file_id: FileId) -> Arc<FileItems> {
34 type FileItemsQuery;
35 storage volatile;
36 use fn module::nameres::file_items;
37 }
38
39 fn _file_item(file_id: FileId, file_item_id: FileItemId) -> SyntaxNode {
40 type FileItemQuery;
41 storage volatile;
42 use fn module::nameres::file_item;
43 }
44
31 fn _input_module_items(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<InputModuleItems>> { 45 fn _input_module_items(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<InputModuleItems>> {
32 type InputModuleItemsQuery; 46 type InputModuleItemsQuery;
33 use fn module::nameres::input_module_items; 47 use fn module::nameres::input_module_items;
diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs
index 648ec5e43..d347a69b0 100644
--- a/crates/ra_analysis/src/descriptors/module/nameres.rs
+++ b/crates/ra_analysis/src/descriptors/module/nameres.rs
@@ -17,27 +17,83 @@
17use std::{ 17use std::{
18 sync::Arc, 18 sync::Arc,
19 time::Instant, 19 time::Instant,
20 ops::Index,
20}; 21};
21 22
22use rustc_hash::FxHashMap; 23use rustc_hash::FxHashMap;
23 24
24use ra_syntax::{ 25use ra_syntax::{
26 SyntaxNode, SyntaxNodeRef, TextRange,
25 SmolStr, SyntaxKind::{self, *}, 27 SmolStr, SyntaxKind::{self, *},
26 ast::{self, ModuleItemOwner} 28 ast::{self, ModuleItemOwner, AstNode}
27}; 29};
28 30
29use crate::{ 31use crate::{
30 Cancelable, 32 Cancelable, FileId,
31 loc2id::{DefId, DefLoc}, 33 loc2id::{DefId, DefLoc},
32 descriptors::{ 34 descriptors::{
33 Path, PathKind, 35 Path, PathKind,
34 DescriptorDatabase, 36 DescriptorDatabase,
35 module::{ModuleId, ModuleTree, ModuleSourceNode}, 37 module::{ModuleId, ModuleTree, ModuleSourceNode},
36 }, 38 },
37 syntax_ptr::{LocalSyntaxPtr},
38 input::SourceRootId, 39 input::SourceRootId,
40 arena::{Arena, Id}
39}; 41};
40 42
43/// Identifier of item within a specific file. This is stable over reparses, so
44/// it's OK to use it as a salsa key/value.
45pub(crate) type FileItemId = Id<SyntaxNode>;
46
47/// Maps item's `SyntaxNode`s to `FileItemId` and back.
48#[derive(Debug, PartialEq, Eq, Default)]
49pub(crate) struct FileItems {
50 arena: Arena<SyntaxNode>,
51}
52
53impl FileItems {
54 fn alloc(&mut self, item: SyntaxNode) -> FileItemId {
55 self.arena.alloc(item)
56 }
57 fn id_of(&self, item: SyntaxNodeRef) -> FileItemId {
58 let (id, _item) = self
59 .arena
60 .iter()
61 .find(|(_id, i)| i.borrowed() == item)
62 .unwrap();
63 id
64 }
65}
66
67impl Index<FileItemId> for FileItems {
68 type Output = SyntaxNode;
69 fn index(&self, idx: FileItemId) -> &SyntaxNode {
70 &self.arena[idx]
71 }
72}
73
74pub(crate) fn file_items(db: &impl DescriptorDatabase, file_id: FileId) -> Arc<FileItems> {
75 let source_file = db.file_syntax(file_id);
76 let source_file = source_file.borrowed();
77 let mut res = FileItems::default();
78 source_file
79 .syntax()
80 .descendants()
81 .filter_map(ast::ModuleItem::cast)
82 .map(|it| it.syntax().owned())
83 .for_each(|it| {
84 res.alloc(it);
85 });
86 Arc::new(res)
87}
88
89pub(crate) fn file_item(
90 db: &impl DescriptorDatabase,
91 file_id: FileId,
92 file_item_id: FileItemId,
93) -> SyntaxNode {
94 db._file_items(file_id)[file_item_id].clone()
95}
96
41/// Item map is the result of the name resolution. Item map contains, for each 97/// Item map is the result of the name resolution. Item map contains, for each
42/// module, the set of visible items. 98/// module, the set of visible items.
43#[derive(Default, Debug, PartialEq, Eq)] 99#[derive(Default, Debug, PartialEq, Eq)]
@@ -62,17 +118,44 @@ pub(crate) struct InputModuleItems {
62 imports: Vec<Import>, 118 imports: Vec<Import>,
63} 119}
64 120
121#[derive(Debug, PartialEq, Eq)]
122struct ModuleItem {
123 id: FileItemId,
124 name: SmolStr,
125 kind: SyntaxKind,
126 vis: Vis,
127}
128
129#[derive(Debug, PartialEq, Eq)]
130enum Vis {
131 // Priv,
132 Other,
133}
134
65#[derive(Debug, Clone, PartialEq, Eq)] 135#[derive(Debug, Clone, PartialEq, Eq)]
66struct Import { 136struct Import {
67 path: Path, 137 path: Path,
68 kind: ImportKind, 138 kind: ImportKind,
69} 139}
70 140
141#[derive(Debug, Clone, Copy, PartialEq, Eq)]
142pub(crate) struct NamedImport {
143 file_item_id: FileItemId,
144 relative_range: TextRange,
145}
146
147impl NamedImport {
148 pub(crate) fn range(&self, db: &impl DescriptorDatabase, file_id: FileId) -> TextRange {
149 let syntax = db._file_item(file_id, self.file_item_id);
150 let offset = syntax.borrowed().range().start();
151 self.relative_range + offset
152 }
153}
154
71#[derive(Debug, Clone, PartialEq, Eq)] 155#[derive(Debug, Clone, PartialEq, Eq)]
72enum ImportKind { 156enum ImportKind {
73 Glob, 157 Glob,
74 // TODO: make offset independent 158 Named(NamedImport),
75 Named(LocalSyntaxPtr),
76} 159}
77 160
78pub(crate) fn input_module_items( 161pub(crate) fn input_module_items(
@@ -82,10 +165,11 @@ pub(crate) fn input_module_items(
82) -> Cancelable<Arc<InputModuleItems>> { 165) -> Cancelable<Arc<InputModuleItems>> {
83 let module_tree = db._module_tree(source_root)?; 166 let module_tree = db._module_tree(source_root)?;
84 let source = module_id.source(&module_tree); 167 let source = module_id.source(&module_tree);
168 let file_items = db._file_items(source.file_id());
85 let res = match source.resolve(db) { 169 let res = match source.resolve(db) {
86 ModuleSourceNode::SourceFile(it) => { 170 ModuleSourceNode::SourceFile(it) => {
87 let items = it.borrowed().items(); 171 let items = it.borrowed().items();
88 InputModuleItems::new(items) 172 InputModuleItems::new(&file_items, items)
89 } 173 }
90 ModuleSourceNode::Module(it) => { 174 ModuleSourceNode::Module(it) => {
91 let items = it 175 let items = it
@@ -93,7 +177,7 @@ pub(crate) fn input_module_items(
93 .item_list() 177 .item_list()
94 .into_iter() 178 .into_iter()
95 .flat_map(|it| it.items()); 179 .flat_map(|it| it.items());
96 InputModuleItems::new(items) 180 InputModuleItems::new(&file_items, items)
97 } 181 }
98 }; 182 };
99 Ok(Arc::new(res)) 183 Ok(Arc::new(res))
@@ -112,7 +196,6 @@ pub(crate) fn item_map(
112 Ok((id, items)) 196 Ok((id, items))
113 }) 197 })
114 .collect::<Cancelable<FxHashMap<_, _>>>()?; 198 .collect::<Cancelable<FxHashMap<_, _>>>()?;
115
116 let mut resolver = Resolver { 199 let mut resolver = Resolver {
117 db: db, 200 db: db,
118 input: &input, 201 input: &input,
@@ -134,8 +217,7 @@ pub(crate) struct Resolution {
134 /// None for unresolved 217 /// None for unresolved
135 pub(crate) def_id: Option<DefId>, 218 pub(crate) def_id: Option<DefId>,
136 /// ident by whitch this is imported into local scope. 219 /// ident by whitch this is imported into local scope.
137 /// TODO: make this offset-independent. 220 pub(crate) import: Option<NamedImport>,
138 pub(crate) import_name: Option<LocalSyntaxPtr>,
139} 221}
140 222
141// #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] 223// #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -150,55 +232,49 @@ pub(crate) struct Resolution {
150// values: Option<T>, 232// values: Option<T>,
151// } 233// }
152 234
153#[derive(Debug, PartialEq, Eq)]
154struct ModuleItem {
155 ptr: LocalSyntaxPtr,
156 name: SmolStr,
157 kind: SyntaxKind,
158 vis: Vis,
159}
160
161#[derive(Debug, PartialEq, Eq)]
162enum Vis {
163 // Priv,
164 Other,
165}
166
167impl InputModuleItems { 235impl InputModuleItems {
168 fn new<'a>(items: impl Iterator<Item = ast::ModuleItem<'a>>) -> InputModuleItems { 236 fn new<'a>(
237 file_items: &FileItems,
238 items: impl Iterator<Item = ast::ModuleItem<'a>>,
239 ) -> InputModuleItems {
169 let mut res = InputModuleItems::default(); 240 let mut res = InputModuleItems::default();
170 for item in items { 241 for item in items {
171 res.add_item(item); 242 res.add_item(file_items, item);
172 } 243 }
173 res 244 res
174 } 245 }
175 246
176 fn add_item(&mut self, item: ast::ModuleItem) -> Option<()> { 247 fn add_item(&mut self, file_items: &FileItems, item: ast::ModuleItem) -> Option<()> {
177 match item { 248 match item {
178 ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(it)?), 249 ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
179 ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(it)?), 250 ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
180 ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(it)?), 251 ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
181 ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(it)?), 252 ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
182 ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(it)?), 253 ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
183 ast::ModuleItem::ImplItem(_) => { 254 ast::ModuleItem::ImplItem(_) => {
184 // impls don't define items 255 // impls don't define items
185 } 256 }
186 ast::ModuleItem::UseItem(it) => self.add_use_item(it), 257 ast::ModuleItem::UseItem(it) => self.add_use_item(file_items, it),
187 ast::ModuleItem::ExternCrateItem(_) => { 258 ast::ModuleItem::ExternCrateItem(_) => {
188 // TODO 259 // TODO
189 } 260 }
190 ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(it)?), 261 ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
191 ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(it)?), 262 ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
192 ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(it)?), 263 ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(file_items, it)?),
193 } 264 }
194 Some(()) 265 Some(())
195 } 266 }
196 267
197 fn add_use_item(&mut self, item: ast::UseItem) { 268 fn add_use_item(&mut self, file_items: &FileItems, item: ast::UseItem) {
198 Path::expand_use_item(item, |path, ptr| { 269 let file_item_id = file_items.id_of(item.syntax());
199 let kind = match ptr { 270 let start_offset = item.syntax().range().start();
271 Path::expand_use_item(item, |path, range| {
272 let kind = match range {
200 None => ImportKind::Glob, 273 None => ImportKind::Glob,
201 Some(ptr) => ImportKind::Named(ptr), 274 Some(range) => ImportKind::Named(NamedImport {
275 file_item_id,
276 relative_range: range - start_offset,
277 }),
202 }; 278 };
203 self.imports.push(Import { kind, path }) 279 self.imports.push(Import { kind, path })
204 }) 280 })
@@ -206,13 +282,13 @@ impl InputModuleItems {
206} 282}
207 283
208impl ModuleItem { 284impl ModuleItem {
209 fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<ModuleItem> { 285 fn new<'a>(file_items: &FileItems, item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {
210 let name = item.name()?.text(); 286 let name = item.name()?.text();
211 let ptr = LocalSyntaxPtr::new(item.syntax());
212 let kind = item.syntax().kind(); 287 let kind = item.syntax().kind();
213 let vis = Vis::Other; 288 let vis = Vis::Other;
289 let id = file_items.id_of(item.syntax());
214 let res = ModuleItem { 290 let res = ModuleItem {
215 ptr, 291 id,
216 name, 292 name,
217 kind, 293 kind,
218 vis, 294 vis,
@@ -252,12 +328,12 @@ where
252 328
253 for import in input.imports.iter() { 329 for import in input.imports.iter() {
254 if let Some(name) = import.path.segments.iter().last() { 330 if let Some(name) = import.path.segments.iter().last() {
255 if let ImportKind::Named(ptr) = import.kind { 331 if let ImportKind::Named(import) = import.kind {
256 module_items.items.insert( 332 module_items.items.insert(
257 name.clone(), 333 name.clone(),
258 Resolution { 334 Resolution {
259 def_id: None, 335 def_id: None,
260 import_name: Some(ptr), 336 import: Some(import),
261 }, 337 },
262 ); 338 );
263 } 339 }
@@ -269,12 +345,14 @@ where
269 // handle submodules separatelly 345 // handle submodules separatelly
270 continue; 346 continue;
271 } 347 }
272 let ptr = item.ptr.into_global(file_id); 348 let def_loc = DefLoc::Item {
273 let def_loc = DefLoc::Item { ptr }; 349 file_id,
350 id: item.id,
351 };
274 let def_id = self.db.id_maps().def_id(def_loc); 352 let def_id = self.db.id_maps().def_id(def_loc);
275 let resolution = Resolution { 353 let resolution = Resolution {
276 def_id: Some(def_id), 354 def_id: Some(def_id),
277 import_name: None, 355 import: None,
278 }; 356 };
279 module_items.items.insert(item.name.clone(), resolution); 357 module_items.items.insert(item.name.clone(), resolution);
280 } 358 }
@@ -287,7 +365,7 @@ where
287 let def_id = self.db.id_maps().def_id(def_loc); 365 let def_id = self.db.id_maps().def_id(def_loc);
288 let resolution = Resolution { 366 let resolution = Resolution {
289 def_id: Some(def_id), 367 def_id: Some(def_id),
290 import_name: None, 368 import: None,
291 }; 369 };
292 module_items.items.insert(name, resolution); 370 module_items.items.insert(name, resolution);
293 } 371 }
@@ -341,7 +419,7 @@ where
341 self.update(module_id, |items| { 419 self.update(module_id, |items| {
342 let res = Resolution { 420 let res = Resolution {
343 def_id: Some(def_id), 421 def_id: Some(def_id),
344 import_name: Some(ptr), 422 import: Some(ptr),
345 }; 423 };
346 items.items.insert(name.clone(), res); 424 items.items.insert(name.clone(), res);
347 }) 425 })
@@ -452,10 +530,11 @@ mod tests {
452 let events = db.log_executed(|| { 530 let events = db.log_executed(|| {
453 db._item_map(source_root).unwrap(); 531 db._item_map(source_root).unwrap();
454 }); 532 });
455 // assert!( 533 assert!(
456 // !format!("{:?}", events).contains("_item_map"), 534 !format!("{:?}", events).contains("_item_map"),
457 // "{:#?}", events 535 "{:#?}",
458 // ) 536 events
537 )
459 } 538 }
460 } 539 }
461} 540}
diff --git a/crates/ra_analysis/src/descriptors/path.rs b/crates/ra_analysis/src/descriptors/path.rs
index 99fca18b1..8279daf4b 100644
--- a/crates/ra_analysis/src/descriptors/path.rs
+++ b/crates/ra_analysis/src/descriptors/path.rs
@@ -1,6 +1,4 @@
1use ra_syntax::{SmolStr, ast, AstNode}; 1use ra_syntax::{SmolStr, ast, AstNode, TextRange};
2
3use crate::syntax_ptr::LocalSyntaxPtr;
4 2
5#[derive(Debug, Clone, PartialEq, Eq)] 3#[derive(Debug, Clone, PartialEq, Eq)]
6pub(crate) struct Path { 4pub(crate) struct Path {
@@ -18,10 +16,7 @@ pub(crate) enum PathKind {
18 16
19impl Path { 17impl Path {
20 /// Calls `cb` with all paths, represented by this use item. 18 /// Calls `cb` with all paths, represented by this use item.
21 pub(crate) fn expand_use_item( 19 pub(crate) fn expand_use_item(item: ast::UseItem, mut cb: impl FnMut(Path, Option<TextRange>)) {
22 item: ast::UseItem,
23 mut cb: impl FnMut(Path, Option<LocalSyntaxPtr>),
24 ) {
25 if let Some(tree) = item.use_tree() { 20 if let Some(tree) = item.use_tree() {
26 expand_use_tree(None, tree, &mut cb); 21 expand_use_tree(None, tree, &mut cb);
27 } 22 }
@@ -77,7 +72,7 @@ impl Path {
77fn expand_use_tree( 72fn expand_use_tree(
78 prefix: Option<Path>, 73 prefix: Option<Path>,
79 tree: ast::UseTree, 74 tree: ast::UseTree,
80 cb: &mut impl FnMut(Path, Option<LocalSyntaxPtr>), 75 cb: &mut impl FnMut(Path, Option<TextRange>),
81) { 76) {
82 if let Some(use_tree_list) = tree.use_tree_list() { 77 if let Some(use_tree_list) = tree.use_tree_list() {
83 let prefix = match tree.path() { 78 let prefix = match tree.path() {
@@ -93,13 +88,13 @@ fn expand_use_tree(
93 } else { 88 } else {
94 if let Some(ast_path) = tree.path() { 89 if let Some(ast_path) = tree.path() {
95 if let Some(path) = convert_path(prefix, ast_path) { 90 if let Some(path) = convert_path(prefix, ast_path) {
96 let ptr = if tree.has_star() { 91 let range = if tree.has_star() {
97 None 92 None
98 } else { 93 } else {
99 let ptr = LocalSyntaxPtr::new(ast_path.segment().unwrap().syntax()); 94 let range = ast_path.segment().unwrap().syntax().range();
100 Some(ptr) 95 Some(range)
101 }; 96 };
102 cb(path, ptr) 97 cb(path, range)
103 } 98 }
104 } 99 }
105 } 100 }