aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/adt.rs3
-rw-r--r--crates/ra_hir/src/ids.rs175
-rw-r--r--crates/ra_hir/src/krate.rs4
-rw-r--r--crates/ra_hir/src/lib.rs178
-rw-r--r--crates/ra_hir/src/macros.rs4
-rw-r--r--crates/ra_hir/src/module/nameres.rs4
6 files changed, 183 insertions, 185 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index e839a5a90..c6463235c 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -1,9 +1,10 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_db::Cancelable;
3use ra_syntax::ast::{self, NameOwner, StructFlavor}; 4use ra_syntax::ast::{self, NameOwner, StructFlavor};
4 5
5use crate::{ 6use crate::{
6 DefId, Cancelable, Name, AsName, 7 DefId, Name, AsName,
7 db::HirDatabase, 8 db::HirDatabase,
8 type_ref::TypeRef, 9 type_ref::TypeRef,
9}; 10};
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 3eba35a24..cd32033f3 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -1,6 +1,10 @@
1use crate::{FileId, MacroCallId, HirDatabase}; 1use ra_db::{SourceRootId, LocationIntener, Cancelable, FileId};
2use ra_syntax::{SourceFileNode, SyntaxKind, SyntaxNode, SyntaxNodeRef, SourceFile, AstNode, ast};
2 3
3use ra_syntax::SourceFileNode; 4use crate::{
5 MacroCallId, HirDatabase, PerNs, ModuleId, Module, Def, Function, Struct, Enum,
6 arena::{Arena, Id},
7};
4 8
5/// hir makes a heavy use of ids: integer (u32) handlers to various things. You 9/// hir makes a heavy use of ids: integer (u32) handlers to various things. You
6/// can think of id as a pointer (but without a lifetime) or a file descriptor 10/// can think of id as a pointer (but without a lifetime) or a file descriptor
@@ -72,3 +76,170 @@ impl From<MacroCallId> for HirFileId {
72 HirFileId(HirFileIdRepr::Macro(macro_call_id)) 76 HirFileId(HirFileIdRepr::Macro(macro_call_id))
73 } 77 }
74} 78}
79
80/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc)
81/// in a specific module.
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
83pub struct DefId(u32);
84ra_db::impl_numeric_id!(DefId);
85
86#[derive(Clone, Debug, PartialEq, Eq, Hash)]
87pub struct DefLoc {
88 pub(crate) kind: DefKind,
89 pub(crate) source_root_id: SourceRootId,
90 pub(crate) module_id: ModuleId,
91 pub(crate) source_item_id: SourceItemId,
92}
93
94#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
95pub(crate) enum DefKind {
96 Module,
97 Function,
98 Struct,
99 Enum,
100 Item,
101
102 StructCtor,
103}
104
105impl DefId {
106 pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
107 db.as_ref().id2loc(self)
108 }
109
110 pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
111 let loc = self.loc(db);
112 let res = match loc.kind {
113 DefKind::Module => {
114 let module = Module::new(db, loc.source_root_id, loc.module_id)?;
115 Def::Module(module)
116 }
117 DefKind::Function => {
118 let function = Function::new(self);
119 Def::Function(function)
120 }
121 DefKind::Struct => {
122 let struct_def = Struct::new(self);
123 Def::Struct(struct_def)
124 }
125 DefKind::Enum => {
126 let enum_def = Enum::new(self);
127 Def::Enum(enum_def)
128 }
129 DefKind::StructCtor => Def::Item,
130 DefKind::Item => Def::Item,
131 };
132 Ok(res)
133 }
134
135 /// For a module, returns that module; for any other def, returns the containing module.
136 pub fn module(self, db: &impl HirDatabase) -> Cancelable<Module> {
137 let loc = self.loc(db);
138 Module::new(db, loc.source_root_id, loc.module_id)
139 }
140}
141
142impl DefLoc {
143 pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
144 db.as_ref().loc2id(&self)
145 }
146}
147
148impl DefKind {
149 pub(crate) fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> {
150 match kind {
151 SyntaxKind::FN_DEF => PerNs::values(DefKind::Function),
152 SyntaxKind::MODULE => PerNs::types(DefKind::Module),
153 SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor),
154 SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum),
155 // These define items, but don't have their own DefKinds yet:
156 SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Item),
157 SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Item),
158 SyntaxKind::CONST_DEF => PerNs::values(DefKind::Item),
159 SyntaxKind::STATIC_DEF => PerNs::values(DefKind::Item),
160 _ => PerNs::none(),
161 }
162 }
163}
164
165/// Identifier of item within a specific file. This is stable over reparses, so
166/// it's OK to use it as a salsa key/value.
167pub(crate) type SourceFileItemId = Id<SyntaxNode>;
168
169#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
170pub struct SourceItemId {
171 pub(crate) file_id: HirFileId,
172 /// None for the whole file.
173 pub(crate) item_id: Option<SourceFileItemId>,
174}
175
176/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back.
177#[derive(Debug, PartialEq, Eq)]
178pub struct SourceFileItems {
179 file_id: HirFileId,
180 arena: Arena<SyntaxNode>,
181}
182
183impl SourceFileItems {
184 pub(crate) fn new(file_id: HirFileId, source_file: SourceFile) -> SourceFileItems {
185 let mut res = SourceFileItems {
186 file_id,
187 arena: Arena::default(),
188 };
189 res.init(source_file);
190 res
191 }
192
193 fn init(&mut self, source_file: SourceFile) {
194 source_file.syntax().descendants().for_each(|it| {
195 if let Some(module_item) = ast::ModuleItem::cast(it) {
196 self.alloc(module_item.syntax().owned());
197 } else if let Some(macro_call) = ast::MacroCall::cast(it) {
198 self.alloc(macro_call.syntax().owned());
199 }
200 });
201 }
202
203 fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId {
204 self.arena.alloc(item)
205 }
206 pub(crate) fn id_of(&self, file_id: HirFileId, item: SyntaxNodeRef) -> SourceFileItemId {
207 assert_eq!(
208 self.file_id, file_id,
209 "SourceFileItems: wrong file, expected {:?}, got {:?}",
210 self.file_id, file_id
211 );
212 self.id_of_unchecked(item)
213 }
214 pub(crate) fn id_of_unchecked(&self, item: SyntaxNodeRef) -> SourceFileItemId {
215 if let Some((id, _)) = self.arena.iter().find(|(_id, i)| i.borrowed() == item) {
216 return id;
217 }
218 // This should not happen. Let's try to give a sensible diagnostics.
219 if let Some((id, i)) = self.arena.iter().find(|(_id, i)| i.range() == item.range()) {
220 // FIXME(#288): whyyy are we getting here?
221 log::error!(
222 "unequal syntax nodes with the same range:\n{:?}\n{:?}",
223 item,
224 i
225 );
226 return id;
227 }
228 panic!(
229 "Can't find {:?} in SourceFileItems:\n{:?}",
230 item,
231 self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
232 );
233 }
234 pub fn id_of_source_file(&self) -> SourceFileItemId {
235 let (id, _syntax) = self.arena.iter().next().unwrap();
236 id
237 }
238}
239
240impl std::ops::Index<SourceFileItemId> for SourceFileItems {
241 type Output = SyntaxNode;
242 fn index(&self, idx: SourceFileItemId) -> &SyntaxNode {
243 &self.arena[idx]
244 }
245}
diff --git a/crates/ra_hir/src/krate.rs b/crates/ra_hir/src/krate.rs
index 4d4f59949..a0821d15d 100644
--- a/crates/ra_hir/src/krate.rs
+++ b/crates/ra_hir/src/krate.rs
@@ -1,6 +1,6 @@
1pub use ra_db::CrateId; 1pub use ra_db::{CrateId, Cancelable};
2 2
3use crate::{HirDatabase, Module, Cancelable, Name, AsName, HirFileId}; 3use crate::{HirDatabase, Module, Name, AsName, HirFileId};
4 4
5/// hir::Crate describes a single crate. It's the main inteface with which 5/// hir::Crate describes a single crate. It's the main inteface with which
6/// crate's dependencies interact. Mostly, it should be just a proxy for the 6/// crate's dependencies interact. Mostly, it should be just a proxy for the
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index c1386601d..5e939b79e 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -32,22 +32,17 @@ mod adt;
32mod type_ref; 32mod type_ref;
33mod ty; 33mod ty;
34 34
35use std::ops::Index;
36
37use ra_syntax::{SyntaxNodeRef, SyntaxNode, SyntaxKind, SourceFile, AstNode, ast};
38use ra_db::{LocationIntener, SourceRootId, FileId, Cancelable};
39
40use crate::{ 35use crate::{
41 db::HirDatabase, 36 db::HirDatabase,
42 arena::{Arena, Id},
43 name::{AsName, KnownName}, 37 name::{AsName, KnownName},
38 ids::{DefKind, SourceItemId, SourceFileItemId, SourceFileItems},
44}; 39};
45 40
46pub use self::{ 41pub use self::{
47 path::{Path, PathKind}, 42 path::{Path, PathKind},
48 name::Name, 43 name::Name,
49 krate::Crate, 44 krate::Crate,
50 ids::HirFileId, 45 ids::{HirFileId, DefId, DefLoc},
51 macros::{MacroDef, MacroInput, MacroExpansion, MacroCallId, MacroCallLoc}, 46 macros::{MacroDef, MacroInput, MacroExpansion, MacroCallId, MacroCallLoc},
52 module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution}, 47 module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution},
53 function::{Function, FnScopes}, 48 function::{Function, FnScopes},
@@ -57,60 +52,6 @@ pub use self::{
57 52
58pub use self::function::FnSignatureInfo; 53pub use self::function::FnSignatureInfo;
59 54
60/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc)
61/// in a specific module.
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
63pub struct DefId(u32);
64ra_db::impl_numeric_id!(DefId);
65
66#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
67pub(crate) enum DefKind {
68 Module,
69 Function,
70 Struct,
71 Enum,
72 Item,
73
74 StructCtor,
75}
76
77#[derive(Clone, Debug, PartialEq, Eq, Hash)]
78pub struct DefLoc {
79 pub(crate) kind: DefKind,
80 source_root_id: SourceRootId,
81 module_id: ModuleId,
82 source_item_id: SourceItemId,
83}
84
85impl DefKind {
86 pub(crate) fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> {
87 match kind {
88 SyntaxKind::FN_DEF => PerNs::values(DefKind::Function),
89 SyntaxKind::MODULE => PerNs::types(DefKind::Module),
90 SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor),
91 SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum),
92 // These define items, but don't have their own DefKinds yet:
93 SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Item),
94 SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Item),
95 SyntaxKind::CONST_DEF => PerNs::values(DefKind::Item),
96 SyntaxKind::STATIC_DEF => PerNs::values(DefKind::Item),
97 _ => PerNs::none(),
98 }
99 }
100}
101
102impl DefId {
103 pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
104 db.as_ref().id2loc(self)
105 }
106}
107
108impl DefLoc {
109 pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
110 db.as_ref().loc2id(&self)
111 }
112}
113
114pub enum Def { 55pub enum Def {
115 Module(Module), 56 Module(Module),
116 Function(Function), 57 Function(Function),
@@ -118,118 +59,3 @@ pub enum Def {
118 Enum(Enum), 59 Enum(Enum),
119 Item, 60 Item,
120} 61}
121
122impl DefId {
123 pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
124 let loc = self.loc(db);
125 let res = match loc.kind {
126 DefKind::Module => {
127 let module = Module::new(db, loc.source_root_id, loc.module_id)?;
128 Def::Module(module)
129 }
130 DefKind::Function => {
131 let function = Function::new(self);
132 Def::Function(function)
133 }
134 DefKind::Struct => {
135 let struct_def = Struct::new(self);
136 Def::Struct(struct_def)
137 }
138 DefKind::Enum => {
139 let enum_def = Enum::new(self);
140 Def::Enum(enum_def)
141 }
142 DefKind::StructCtor => Def::Item,
143 DefKind::Item => Def::Item,
144 };
145 Ok(res)
146 }
147
148 /// For a module, returns that module; for any other def, returns the containing module.
149 pub fn module(self, db: &impl HirDatabase) -> Cancelable<Module> {
150 let loc = self.loc(db);
151 Module::new(db, loc.source_root_id, loc.module_id)
152 }
153}
154
155/// Identifier of item within a specific file. This is stable over reparses, so
156/// it's OK to use it as a salsa key/value.
157pub(crate) type SourceFileItemId = Id<SyntaxNode>;
158
159#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
160pub struct SourceItemId {
161 file_id: HirFileId,
162 /// None for the whole file.
163 item_id: Option<SourceFileItemId>,
164}
165
166/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back.
167#[derive(Debug, PartialEq, Eq)]
168pub struct SourceFileItems {
169 file_id: HirFileId,
170 arena: Arena<SyntaxNode>,
171}
172
173impl SourceFileItems {
174 fn new(file_id: HirFileId, source_file: SourceFile) -> SourceFileItems {
175 let mut res = SourceFileItems {
176 file_id,
177 arena: Arena::default(),
178 };
179 res.init(source_file);
180 res
181 }
182
183 fn init(&mut self, source_file: SourceFile) {
184 source_file.syntax().descendants().for_each(|it| {
185 if let Some(module_item) = ast::ModuleItem::cast(it) {
186 self.alloc(module_item.syntax().owned());
187 } else if let Some(macro_call) = ast::MacroCall::cast(it) {
188 self.alloc(macro_call.syntax().owned());
189 }
190 });
191 }
192
193 fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId {
194 self.arena.alloc(item)
195 }
196 pub fn id_of(&self, file_id: HirFileId, item: SyntaxNodeRef) -> SourceFileItemId {
197 assert_eq!(
198 self.file_id, file_id,
199 "SourceFileItems: wrong file, expected {:?}, got {:?}",
200 self.file_id, file_id
201 );
202 self.id_of_unchecked(item)
203 }
204 fn id_of_unchecked(&self, item: SyntaxNodeRef) -> SourceFileItemId {
205 if let Some((id, _)) = self.arena.iter().find(|(_id, i)| i.borrowed() == item) {
206 return id;
207 }
208 // This should not happen. Let's try to give a sensible diagnostics.
209 if let Some((id, i)) = self.arena.iter().find(|(_id, i)| i.range() == item.range()) {
210 // FIXME(#288): whyyy are we getting here?
211 log::error!(
212 "unequal syntax nodes with the same range:\n{:?}\n{:?}",
213 item,
214 i
215 );
216 return id;
217 }
218 panic!(
219 "Can't find {:?} in SourceFileItems:\n{:?}",
220 item,
221 self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
222 );
223 }
224 pub fn id_of_source_file(&self) -> SourceFileItemId {
225 let (id, _syntax) = self.arena.iter().next().unwrap();
226 id
227 }
228}
229
230impl Index<SourceFileItemId> for SourceFileItems {
231 type Output = SyntaxNode;
232 fn index(&self, idx: SourceFileItemId) -> &SyntaxNode {
233 &self.arena[idx]
234 }
235}
diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs
index 1f141dbac..288fbe3c6 100644
--- a/crates/ra_hir/src/macros.rs
+++ b/crates/ra_hir/src/macros.rs
@@ -1,12 +1,12 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_db::{LocalSyntaxPtr, LocationIntener}; 3use ra_db::{SourceRootId, LocalSyntaxPtr, LocationIntener};
4use ra_syntax::{ 4use ra_syntax::{
5 TextRange, TextUnit, SourceFileNode, AstNode, SyntaxNode, 5 TextRange, TextUnit, SourceFileNode, AstNode, SyntaxNode,
6 ast::{self, NameOwner}, 6 ast::{self, NameOwner},
7}; 7};
8 8
9use crate::{SourceRootId, module::ModuleId, SourceItemId, HirDatabase}; 9use crate::{module::ModuleId, SourceItemId, HirDatabase};
10 10
11/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) 11/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc)
12/// in a specific module. 12/// in a specific module.
diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs
index cc60ba077..40aa33ffa 100644
--- a/crates/ra_hir/src/module/nameres.rs
+++ b/crates/ra_hir/src/module/nameres.rs
@@ -22,10 +22,10 @@ use ra_syntax::{
22 SyntaxKind::{self, *}, 22 SyntaxKind::{self, *},
23 ast::{self, AstNode} 23 ast::{self, AstNode}
24}; 24};
25use ra_db::SourceRootId; 25use ra_db::{SourceRootId, Cancelable, FileId};
26 26
27use crate::{ 27use crate::{
28 Cancelable, HirFileId, FileId, 28 HirFileId,
29 DefId, DefLoc, DefKind, 29 DefId, DefLoc, DefKind,
30 SourceItemId, SourceFileItemId, SourceFileItems, 30 SourceItemId, SourceFileItemId, SourceFileItems,
31 Path, PathKind, 31 Path, PathKind,