aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres/lower.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/nameres/lower.rs')
-rw-r--r--crates/ra_hir/src/nameres/lower.rs182
1 files changed, 15 insertions, 167 deletions
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs
index 6bca14444..52448644c 100644
--- a/crates/ra_hir/src/nameres/lower.rs
+++ b/crates/ra_hir/src/nameres/lower.rs
@@ -1,157 +1,17 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 TextRange, SyntaxKind, AstNode, SourceFile, TreeArc, 4 SyntaxKind, AstNode, SourceFile, TreeArc,
5 ast::{self, ModuleItemOwner}, 5 ast::{self, ModuleItemOwner},
6}; 6};
7use ra_db::{SourceRootId, LocalSyntaxPtr}; 7use ra_db::{SourceRootId, LocalSyntaxPtr};
8use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; 8use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
9 9
10use crate::{ 10use crate::{
11 SourceItemId, SourceFileItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, 11 SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems,
12 HirFileId, MacroCallLoc, AsName, 12 HirFileId, MacroCallLoc, AsName,
13 module_tree::ModuleId 13 module_tree::ModuleId
14}; 14};
15/// A set of items and imports declared inside a module, without relation to
16/// other modules.
17///
18/// This sits in-between raw syntax and name resolution and allows us to avoid
19/// recomputing name res: if two instance of `InputModuleItems` are the same, we
20/// can avoid redoing name resolution.
21#[derive(Debug, Default, PartialEq, Eq)]
22pub struct InputModuleItems {
23 pub(crate) items: Vec<ModuleItem>,
24 pub(super) imports: Vec<Import>,
25}
26
27impl InputModuleItems {
28 pub(crate) fn input_module_items_query(
29 db: &impl HirDatabase,
30 source_root_id: SourceRootId,
31 module_id: ModuleId,
32 ) -> Arc<InputModuleItems> {
33 let module_tree = db.module_tree(source_root_id);
34 let source = module_id.source(&module_tree);
35 let file_id = source.file_id;
36 let source = ModuleSource::from_source_item_id(db, source);
37 let mut res = InputModuleItems::default();
38 match source {
39 ModuleSource::SourceFile(it) => res.fill(
40 db,
41 source_root_id,
42 module_id,
43 file_id,
44 &mut it.items_with_macros(),
45 ),
46 ModuleSource::Module(it) => {
47 if let Some(item_list) = it.item_list() {
48 res.fill(
49 db,
50 source_root_id,
51 module_id,
52 file_id,
53 &mut item_list.items_with_macros(),
54 )
55 }
56 }
57 };
58 Arc::new(res)
59 }
60
61 fn fill(
62 &mut self,
63 db: &impl HirDatabase,
64 source_root_id: SourceRootId,
65 module_id: ModuleId,
66 file_id: HirFileId,
67 items: &mut Iterator<Item = ast::ItemOrMacro>,
68 ) {
69 let file_items = db.file_items(file_id);
70
71 for item in items {
72 match item {
73 ast::ItemOrMacro::Item(it) => {
74 self.add_item(file_id, &file_items, it);
75 }
76 ast::ItemOrMacro::Macro(macro_call) => {
77 let item_id = file_items.id_of_unchecked(macro_call.syntax());
78 let loc = MacroCallLoc {
79 source_root_id,
80 module_id,
81 source_item_id: SourceItemId {
82 file_id,
83 item_id: Some(item_id),
84 },
85 };
86 let id = loc.id(db);
87 let file_id = HirFileId::from(id);
88 let file_items = db.file_items(file_id);
89 //FIXME: expand recursively
90 for item in db.hir_source_file(file_id).items() {
91 self.add_item(file_id, &file_items, item);
92 }
93 }
94 }
95 }
96 }
97
98 fn add_item(
99 &mut self,
100 file_id: HirFileId,
101 file_items: &SourceFileItems,
102 item: &ast::ModuleItem,
103 ) -> Option<()> {
104 match item.kind() {
105 ast::ModuleItemKind::StructDef(it) => {
106 self.items.push(ModuleItem::new(file_id, file_items, it)?)
107 }
108 ast::ModuleItemKind::EnumDef(it) => {
109 self.items.push(ModuleItem::new(file_id, file_items, it)?)
110 }
111 ast::ModuleItemKind::FnDef(it) => {
112 self.items.push(ModuleItem::new(file_id, file_items, it)?)
113 }
114 ast::ModuleItemKind::TraitDef(it) => {
115 self.items.push(ModuleItem::new(file_id, file_items, it)?)
116 }
117 ast::ModuleItemKind::TypeDef(it) => {
118 self.items.push(ModuleItem::new(file_id, file_items, it)?)
119 }
120 ast::ModuleItemKind::ImplBlock(_) => {
121 // impls don't define items
122 }
123 ast::ModuleItemKind::UseItem(it) => self.add_use_item(file_items, it),
124 ast::ModuleItemKind::ExternCrateItem(_) => {
125 // TODO
126 }
127 ast::ModuleItemKind::ConstDef(it) => {
128 self.items.push(ModuleItem::new(file_id, file_items, it)?)
129 }
130 ast::ModuleItemKind::StaticDef(it) => {
131 self.items.push(ModuleItem::new(file_id, file_items, it)?)
132 }
133 ast::ModuleItemKind::Module(it) => {
134 self.items.push(ModuleItem::new(file_id, file_items, it)?)
135 }
136 }
137 Some(())
138 }
139
140 fn add_use_item(&mut self, file_items: &SourceFileItems, item: &ast::UseItem) {
141 let file_item_id = file_items.id_of_unchecked(item.syntax());
142 let start_offset = item.syntax().range().start();
143 Path::expand_use_item(item, |path, segment| {
144 let kind = match segment {
145 None => ImportKind::Glob,
146 Some(segment) => ImportKind::Named(NamedImport {
147 file_item_id,
148 relative_range: segment.syntax().range() - start_offset,
149 }),
150 };
151 self.imports.push(Import { kind, path })
152 })
153 }
154}
155 15
156#[derive(Debug, PartialEq, Eq)] 16#[derive(Debug, PartialEq, Eq)]
157pub(super) enum Vis { 17pub(super) enum Vis {
@@ -188,27 +48,9 @@ impl ModuleItem {
188 } 48 }
189} 49}
190 50
191#[derive(Debug, Clone, PartialEq, Eq)]
192pub(super) struct Import {
193 pub(super) path: Path,
194 pub(super) kind: ImportKind,
195}
196
197#[derive(Debug, Clone, Copy, PartialEq, Eq)]
198pub struct NamedImport {
199 pub file_item_id: SourceFileItemId,
200 pub relative_range: TextRange,
201}
202
203#[derive(Debug, Clone, PartialEq, Eq)]
204pub(super) enum ImportKind {
205 Glob,
206 Named(NamedImport),
207}
208
209#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 51#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
210pub struct LoweredImport(RawId); 52pub struct ImportId(RawId);
211impl_arena_id!(LoweredImport); 53impl_arena_id!(ImportId);
212 54
213#[derive(Debug, PartialEq, Eq)] 55#[derive(Debug, PartialEq, Eq)]
214pub(super) struct ImportData { 56pub(super) struct ImportData {
@@ -216,24 +58,30 @@ pub(super) struct ImportData {
216 pub(super) is_glob: bool, 58 pub(super) is_glob: bool,
217} 59}
218 60
61/// A set of items and imports declared inside a module, without relation to
62/// other modules.
63///
64/// This sits in-between raw syntax and name resolution and allows us to avoid
65/// recomputing name res: if two instance of `InputModuleItems` are the same, we
66/// can avoid redoing name resolution.
219#[derive(Debug, Default, PartialEq, Eq)] 67#[derive(Debug, Default, PartialEq, Eq)]
220pub struct LoweredModule { 68pub struct LoweredModule {
221 pub(super) items: Vec<ModuleItem>, 69 pub(crate) items: Vec<ModuleItem>,
222 pub(super) imports: Arena<LoweredImport, ImportData>, 70 pub(super) imports: Arena<ImportId, ImportData>,
223} 71}
224 72
225#[derive(Debug, Default, PartialEq, Eq)] 73#[derive(Debug, Default, PartialEq, Eq)]
226pub struct ImportSourceMap { 74pub struct ImportSourceMap {
227 map: ArenaMap<LoweredImport, LocalSyntaxPtr>, 75 map: ArenaMap<ImportId, LocalSyntaxPtr>,
228} 76}
229 77
230impl ImportSourceMap { 78impl ImportSourceMap {
231 fn insert(&mut self, import: LoweredImport, segment: &ast::PathSegment) { 79 fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) {
232 self.map 80 self.map
233 .insert(import, LocalSyntaxPtr::new(segment.syntax())) 81 .insert(import, LocalSyntaxPtr::new(segment.syntax()))
234 } 82 }
235 83
236 pub fn get(&self, source: &ModuleSource, import: LoweredImport) -> TreeArc<ast::PathSegment> { 84 pub fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> {
237 let file = match source { 85 let file = match source {
238 ModuleSource::SourceFile(file) => &*file, 86 ModuleSource::SourceFile(file) => &*file,
239 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(), 87 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),