aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/code_model_api.rs4
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs18
-rw-r--r--crates/ra_hir/src/db.rs12
-rw-r--r--crates/ra_hir/src/ids.rs75
-rw-r--r--crates/ra_hir/src/lib.rs4
-rw-r--r--crates/ra_hir/src/nameres.rs20
-rw-r--r--crates/ra_hir/src/nameres/collector.rs69
-rw-r--r--crates/ra_hir/src/nameres/raw.rs69
-rw-r--r--crates/ra_hir/src/source_binder.rs10
-rw-r--r--crates/ra_hir/src/source_id.rs157
10 files changed, 231 insertions, 207 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 88c13566c..624c25c4d 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -13,7 +13,7 @@ use crate::{
13 adt::{EnumVariantId, StructFieldId, VariantDef}, 13 adt::{EnumVariantId, StructFieldId, VariantDef},
14 generics::GenericParams, 14 generics::GenericParams,
15 docs::{Documentation, Docs, docs_from_ast}, 15 docs::{Documentation, Docs, docs_from_ast},
16 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, 16 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeAliasId},
17 impl_block::ImplBlock, 17 impl_block::ImplBlock,
18 resolve::Resolver, 18 resolve::Resolver,
19 diagnostics::DiagnosticSink, 19 diagnostics::DiagnosticSink,
@@ -672,7 +672,7 @@ impl Docs for Trait {
672 672
673#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 673#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
674pub struct TypeAlias { 674pub struct TypeAlias {
675 pub(crate) id: TypeId, 675 pub(crate) id: TypeAliasId,
676} 676}
677 677
678impl TypeAlias { 678impl TypeAlias {
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index 790e2b80f..0edb8ade5 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -1,18 +1,18 @@
1use ra_db::FileId; 1use ra_db::FileId;
2use ra_syntax::{ast, TreeArc, AstNode}; 2use ra_syntax::{ast, TreeArc};
3 3
4use crate::{ 4use crate::{
5 Module, ModuleSource, Name, 5 Module, ModuleSource, Name, AstId,
6 nameres::{CrateModuleId, ImportId}, 6 nameres::{CrateModuleId, ImportId},
7 HirDatabase, DefDatabase, 7 HirDatabase, DefDatabase,
8 HirFileId, SourceItemId, 8 HirFileId,
9}; 9};
10 10
11impl ModuleSource { 11impl ModuleSource {
12 pub(crate) fn new( 12 pub(crate) fn new(
13 db: &impl DefDatabase, 13 db: &impl DefDatabase,
14 file_id: Option<FileId>, 14 file_id: Option<FileId>,
15 decl_id: Option<SourceItemId>, 15 decl_id: Option<AstId<ast::Module>>,
16 ) -> ModuleSource { 16 ) -> ModuleSource {
17 match (file_id, decl_id) { 17 match (file_id, decl_id) {
18 (Some(file_id), _) => { 18 (Some(file_id), _) => {
@@ -20,8 +20,7 @@ impl ModuleSource {
20 ModuleSource::SourceFile(source_file) 20 ModuleSource::SourceFile(source_file)
21 } 21 }
22 (None, Some(item_id)) => { 22 (None, Some(item_id)) => {
23 let module = db.file_item(item_id); 23 let module = item_id.to_node(db);
24 let module = ast::Module::cast(&*module).unwrap();
25 assert!(module.item_list().is_some(), "expected inline module"); 24 assert!(module.item_list().is_some(), "expected inline module");
26 ModuleSource::Module(module.to_owned()) 25 ModuleSource::Module(module.to_owned())
27 } 26 }
@@ -55,7 +54,7 @@ impl Module {
55 let decl_id = def_map[self.module_id].declaration; 54 let decl_id = def_map[self.module_id].declaration;
56 let file_id = def_map[self.module_id].definition; 55 let file_id = def_map[self.module_id].definition;
57 let module_source = ModuleSource::new(db, file_id, decl_id); 56 let module_source = ModuleSource::new(db, file_id, decl_id);
58 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id); 57 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id());
59 (file_id, module_source) 58 (file_id, module_source)
60 } 59 }
61 60
@@ -65,9 +64,8 @@ impl Module {
65 ) -> Option<(HirFileId, TreeArc<ast::Module>)> { 64 ) -> Option<(HirFileId, TreeArc<ast::Module>)> {
66 let def_map = db.crate_def_map(self.krate); 65 let def_map = db.crate_def_map(self.krate);
67 let decl = def_map[self.module_id].declaration?; 66 let decl = def_map[self.module_id].declaration?;
68 let syntax_node = db.file_item(decl); 67 let ast = decl.to_node(db);
69 let ast = ast::Module::cast(&syntax_node).unwrap().to_owned(); 68 Some((decl.file_id(), ast))
70 Some((decl.file_id, ast))
71 } 69 }
72 70
73 pub(crate) fn import_source_impl( 71 pub(crate) fn import_source_impl(
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 3296b9b31..147005848 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -4,7 +4,7 @@ use ra_syntax::{SyntaxNode, TreeArc, SourceFile};
4use ra_db::{SourceDatabase, salsa}; 4use ra_db::{SourceDatabase, salsa};
5 5
6use crate::{ 6use crate::{
7 HirFileId, MacroDefId, SourceFileItems, SourceItemId, Crate, Module, HirInterner, 7 HirFileId, MacroDefId, AstIdMap, ErasedFileAstId, Crate, Module, HirInterner,
8 Function, FnSignature, ExprScopes, TypeAlias, 8 Function, FnSignature, ExprScopes, TypeAlias,
9 Struct, Enum, StructField, 9 Struct, Enum, StructField,
10 Const, ConstSignature, Static, 10 Const, ConstSignature, Static,
@@ -22,7 +22,7 @@ pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> {
22 #[salsa::invoke(crate::ids::macro_def_query)] 22 #[salsa::invoke(crate::ids::macro_def_query)]
23 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>; 23 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>;
24 24
25 #[salsa::invoke(HirFileId::hir_parse)] 25 #[salsa::invoke(HirFileId::hir_parse_query)]
26 fn hir_parse(&self, file_id: HirFileId) -> TreeArc<SourceFile>; 26 fn hir_parse(&self, file_id: HirFileId) -> TreeArc<SourceFile>;
27 27
28 #[salsa::invoke(crate::adt::StructData::struct_data_query)] 28 #[salsa::invoke(crate::adt::StructData::struct_data_query)]
@@ -34,11 +34,11 @@ pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> {
34 #[salsa::invoke(crate::traits::TraitData::trait_data_query)] 34 #[salsa::invoke(crate::traits::TraitData::trait_data_query)]
35 fn trait_data(&self, t: Trait) -> Arc<TraitData>; 35 fn trait_data(&self, t: Trait) -> Arc<TraitData>;
36 36
37 #[salsa::invoke(crate::source_id::SourceFileItems::file_items_query)] 37 #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)]
38 fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>; 38 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
39 39
40 #[salsa::invoke(crate::source_id::SourceFileItems::file_item_query)] 40 #[salsa::invoke(crate::source_id::AstIdMap::file_item_query)]
41 fn file_item(&self, source_item_id: SourceItemId) -> TreeArc<SyntaxNode>; 41 fn ast_id_to_node(&self, file_id: HirFileId, ast_id: ErasedFileAstId) -> TreeArc<SyntaxNode>;
42 42
43 #[salsa::invoke(RawItems::raw_items_query)] 43 #[salsa::invoke(RawItems::raw_items_query)]
44 fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>; 44 fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>;
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index e73dd5d21..eb9939df7 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -1,5 +1,4 @@
1use std::{ 1use std::{
2 marker::PhantomData,
3 hash::{Hash, Hasher}, 2 hash::{Hash, Hasher},
4 sync::Arc, 3 sync::Arc,
5}; 4};
@@ -10,7 +9,7 @@ use ra_arena::{RawId, ArenaId, impl_arena_id};
10use mbe::MacroRules; 9use mbe::MacroRules;
11 10
12use crate::{ 11use crate::{
13 Module, DefDatabase, SourceItemId, SourceFileItemId, 12 Module, DefDatabase, AstId, FileAstId,
14}; 13};
15 14
16#[derive(Debug, Default)] 15#[derive(Debug, Default)]
@@ -22,7 +21,7 @@ pub struct HirInterner {
22 consts: LocationInterner<ItemLoc<ast::ConstDef>, ConstId>, 21 consts: LocationInterner<ItemLoc<ast::ConstDef>, ConstId>,
23 statics: LocationInterner<ItemLoc<ast::StaticDef>, StaticId>, 22 statics: LocationInterner<ItemLoc<ast::StaticDef>, StaticId>,
24 traits: LocationInterner<ItemLoc<ast::TraitDef>, TraitId>, 23 traits: LocationInterner<ItemLoc<ast::TraitDef>, TraitId>,
25 types: LocationInterner<ItemLoc<ast::TypeAliasDef>, TypeId>, 24 types: LocationInterner<ItemLoc<ast::TypeAliasDef>, TypeAliasId>,
26} 25}
27 26
28impl HirInterner { 27impl HirInterner {
@@ -68,7 +67,7 @@ impl HirFileId {
68 HirFileIdRepr::File(file_id) => file_id, 67 HirFileIdRepr::File(file_id) => file_id,
69 HirFileIdRepr::Macro(macro_call_id) => { 68 HirFileIdRepr::Macro(macro_call_id) => {
70 let loc = macro_call_id.loc(db); 69 let loc = macro_call_id.loc(db);
71 loc.source_item_id.file_id.original_file(db) 70 loc.ast_id.file_id().original_file(db)
72 } 71 }
73 } 72 }
74 } 73 }
@@ -83,7 +82,10 @@ impl HirFileId {
83 } 82 }
84 } 83 }
85 84
86 pub(crate) fn hir_parse(db: &impl DefDatabase, file_id: HirFileId) -> TreeArc<SourceFile> { 85 pub(crate) fn hir_parse_query(
86 db: &impl DefDatabase,
87 file_id: HirFileId,
88 ) -> TreeArc<SourceFile> {
87 match file_id.0 { 89 match file_id.0 {
88 HirFileIdRepr::File(file_id) => db.parse(file_id), 90 HirFileIdRepr::File(file_id) => db.parse(file_id),
89 HirFileIdRepr::Macro(macro_call_id) => { 91 HirFileIdRepr::Macro(macro_call_id) => {
@@ -96,8 +98,7 @@ impl HirFileId {
96 98
97fn parse_macro(db: &impl DefDatabase, macro_call_id: MacroCallId) -> Option<TreeArc<SourceFile>> { 99fn parse_macro(db: &impl DefDatabase, macro_call_id: MacroCallId) -> Option<TreeArc<SourceFile>> {
98 let loc = macro_call_id.loc(db); 100 let loc = macro_call_id.loc(db);
99 let syntax = db.file_item(loc.source_item_id); 101 let macro_call = loc.ast_id.to_node(db);
100 let macro_call = ast::MacroCall::cast(&syntax).unwrap();
101 let (macro_arg, _) = macro_call.token_tree().and_then(mbe::ast_to_token_tree)?; 102 let (macro_arg, _) = macro_call.token_tree().and_then(mbe::ast_to_token_tree)?;
102 103
103 let macro_rules = db.macro_def(loc.def)?; 104 let macro_rules = db.macro_def(loc.def)?;
@@ -124,15 +125,10 @@ impl From<MacroCallId> for HirFileId {
124} 125}
125 126
126#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 127#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
127pub enum MacroDefId { 128pub struct MacroDefId(pub(crate) AstId<ast::MacroCall>);
128 MacroByExample { source_item_id: SourceItemId },
129}
130 129
131pub(crate) fn macro_def_query(db: &impl DefDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> { 130pub(crate) fn macro_def_query(db: &impl DefDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> {
132 let syntax_node = match id { 131 let macro_call = id.0.to_node(db);
133 MacroDefId::MacroByExample { source_item_id } => db.file_item(source_item_id),
134 };
135 let macro_call = ast::MacroCall::cast(&syntax_node).unwrap();
136 let arg = macro_call.token_tree()?; 132 let arg = macro_call.token_tree()?;
137 let (tt, _) = mbe::ast_to_token_tree(arg)?; 133 let (tt, _) = mbe::ast_to_token_tree(arg)?;
138 let rules = MacroRules::parse(&tt).ok()?; 134 let rules = MacroRules::parse(&tt).ok()?;
@@ -148,7 +144,7 @@ impl_arena_id!(MacroCallId);
148#[derive(Debug, Clone, PartialEq, Eq, Hash)] 144#[derive(Debug, Clone, PartialEq, Eq, Hash)]
149pub struct MacroCallLoc { 145pub struct MacroCallLoc {
150 pub(crate) def: MacroDefId, 146 pub(crate) def: MacroDefId,
151 pub(crate) source_item_id: SourceItemId, 147 pub(crate) ast_id: AstId<ast::MacroCall>,
152} 148}
153 149
154impl MacroCallId { 150impl MacroCallId {
@@ -158,7 +154,6 @@ impl MacroCallId {
158} 154}
159 155
160impl MacroCallLoc { 156impl MacroCallLoc {
161 #[allow(unused)]
162 pub(crate) fn id(&self, db: &impl AsRef<HirInterner>) -> MacroCallId { 157 pub(crate) fn id(&self, db: &impl AsRef<HirInterner>) -> MacroCallId {
163 db.as_ref().macros.loc2id(&self) 158 db.as_ref().macros.loc2id(&self)
164 } 159 }
@@ -167,26 +162,25 @@ impl MacroCallLoc {
167#[derive(Debug)] 162#[derive(Debug)]
168pub struct ItemLoc<N: AstNode> { 163pub struct ItemLoc<N: AstNode> {
169 pub(crate) module: Module, 164 pub(crate) module: Module,
170 raw: SourceItemId, 165 ast_id: AstId<N>,
171 _ty: PhantomData<N>,
172} 166}
173 167
174impl<N: AstNode> PartialEq for ItemLoc<N> { 168impl<N: AstNode> PartialEq for ItemLoc<N> {
175 fn eq(&self, other: &Self) -> bool { 169 fn eq(&self, other: &Self) -> bool {
176 self.module == other.module && self.raw == other.raw 170 self.module == other.module && self.ast_id == other.ast_id
177 } 171 }
178} 172}
179impl<N: AstNode> Eq for ItemLoc<N> {} 173impl<N: AstNode> Eq for ItemLoc<N> {}
180impl<N: AstNode> Hash for ItemLoc<N> { 174impl<N: AstNode> Hash for ItemLoc<N> {
181 fn hash<H: Hasher>(&self, hasher: &mut H) { 175 fn hash<H: Hasher>(&self, hasher: &mut H) {
182 self.module.hash(hasher); 176 self.module.hash(hasher);
183 self.raw.hash(hasher); 177 self.ast_id.hash(hasher);
184 } 178 }
185} 179}
186 180
187impl<N: AstNode> Clone for ItemLoc<N> { 181impl<N: AstNode> Clone for ItemLoc<N> {
188 fn clone(&self) -> ItemLoc<N> { 182 fn clone(&self) -> ItemLoc<N> {
189 ItemLoc { module: self.module, raw: self.raw, _ty: PhantomData } 183 ItemLoc { module: self.module, ast_id: self.ast_id }
190 } 184 }
191} 185}
192 186
@@ -213,26 +207,19 @@ impl<'a, DB: DefDatabase> LocationCtx<&'a DB> {
213pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone { 207pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
214 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<N>, Self>; 208 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<N>, Self>;
215 fn from_ast(ctx: LocationCtx<&impl DefDatabase>, ast: &N) -> Self { 209 fn from_ast(ctx: LocationCtx<&impl DefDatabase>, ast: &N) -> Self {
216 let items = ctx.db.file_items(ctx.file_id); 210 let items = ctx.db.ast_id_map(ctx.file_id);
217 let item_id = items.id_of(ctx.file_id, ast.syntax()); 211 let item_id = items.ast_id(ast);
218 Self::from_source_item_id_unchecked(ctx, item_id) 212 Self::from_ast_id(ctx, item_id)
219 } 213 }
220 fn from_source_item_id_unchecked( 214 fn from_ast_id(ctx: LocationCtx<&impl DefDatabase>, ast_id: FileAstId<N>) -> Self {
221 ctx: LocationCtx<&impl DefDatabase>, 215 let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) };
222 item_id: SourceFileItemId,
223 ) -> Self {
224 let raw = SourceItemId { file_id: ctx.file_id, item_id };
225 let loc = ItemLoc { module: ctx.module, raw, _ty: PhantomData };
226
227 Self::interner(ctx.db.as_ref()).loc2id(&loc) 216 Self::interner(ctx.db.as_ref()).loc2id(&loc)
228 } 217 }
229 fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<N>) { 218 fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<N>) {
230 let int = Self::interner(db.as_ref()); 219 let int = Self::interner(db.as_ref());
231 let loc = int.id2loc(self); 220 let loc = int.id2loc(self);
232 let syntax = db.file_item(loc.raw); 221 let ast = loc.ast_id.to_node(db);
233 let ast = 222 (loc.ast_id.file_id(), ast)
234 N::cast(&syntax).unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", loc.raw)).to_owned();
235 (loc.raw.file_id, ast)
236 } 223 }
237 fn module(self, db: &impl DefDatabase) -> Module { 224 fn module(self, db: &impl DefDatabase) -> Module {
238 let int = Self::interner(db.as_ref()); 225 let int = Self::interner(db.as_ref());
@@ -242,7 +229,7 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
242} 229}
243 230
244#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 231#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
245pub struct FunctionId(RawId); 232pub(crate) struct FunctionId(RawId);
246impl_arena_id!(FunctionId); 233impl_arena_id!(FunctionId);
247impl AstItemDef<ast::FnDef> for FunctionId { 234impl AstItemDef<ast::FnDef> for FunctionId {
248 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::FnDef>, Self> { 235 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::FnDef>, Self> {
@@ -251,7 +238,7 @@ impl AstItemDef<ast::FnDef> for FunctionId {
251} 238}
252 239
253#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 240#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
254pub struct StructId(RawId); 241pub(crate) struct StructId(RawId);
255impl_arena_id!(StructId); 242impl_arena_id!(StructId);
256impl AstItemDef<ast::StructDef> for StructId { 243impl AstItemDef<ast::StructDef> for StructId {
257 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StructDef>, Self> { 244 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StructDef>, Self> {
@@ -260,7 +247,7 @@ impl AstItemDef<ast::StructDef> for StructId {
260} 247}
261 248
262#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 249#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
263pub struct EnumId(RawId); 250pub(crate) struct EnumId(RawId);
264impl_arena_id!(EnumId); 251impl_arena_id!(EnumId);
265impl AstItemDef<ast::EnumDef> for EnumId { 252impl AstItemDef<ast::EnumDef> for EnumId {
266 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::EnumDef>, Self> { 253 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::EnumDef>, Self> {
@@ -269,7 +256,7 @@ impl AstItemDef<ast::EnumDef> for EnumId {
269} 256}
270 257
271#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 258#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
272pub struct ConstId(RawId); 259pub(crate) struct ConstId(RawId);
273impl_arena_id!(ConstId); 260impl_arena_id!(ConstId);
274impl AstItemDef<ast::ConstDef> for ConstId { 261impl AstItemDef<ast::ConstDef> for ConstId {
275 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::ConstDef>, Self> { 262 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::ConstDef>, Self> {
@@ -278,7 +265,7 @@ impl AstItemDef<ast::ConstDef> for ConstId {
278} 265}
279 266
280#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 267#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
281pub struct StaticId(RawId); 268pub(crate) struct StaticId(RawId);
282impl_arena_id!(StaticId); 269impl_arena_id!(StaticId);
283impl AstItemDef<ast::StaticDef> for StaticId { 270impl AstItemDef<ast::StaticDef> for StaticId {
284 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StaticDef>, Self> { 271 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StaticDef>, Self> {
@@ -287,7 +274,7 @@ impl AstItemDef<ast::StaticDef> for StaticId {
287} 274}
288 275
289#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 276#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
290pub struct TraitId(RawId); 277pub(crate) struct TraitId(RawId);
291impl_arena_id!(TraitId); 278impl_arena_id!(TraitId);
292impl AstItemDef<ast::TraitDef> for TraitId { 279impl AstItemDef<ast::TraitDef> for TraitId {
293 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TraitDef>, Self> { 280 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TraitDef>, Self> {
@@ -296,9 +283,9 @@ impl AstItemDef<ast::TraitDef> for TraitId {
296} 283}
297 284
298#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 285#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
299pub struct TypeId(RawId); 286pub(crate) struct TypeAliasId(RawId);
300impl_arena_id!(TypeId); 287impl_arena_id!(TypeAliasId);
301impl AstItemDef<ast::TypeAliasDef> for TypeId { 288impl AstItemDef<ast::TypeAliasDef> for TypeAliasId {
302 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TypeAliasDef>, Self> { 289 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TypeAliasDef>, Self> {
303 &interner.types 290 &interner.types
304 } 291 }
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index ac2585de0..7c603bbd3 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -48,13 +48,13 @@ mod marks;
48use crate::{ 48use crate::{
49 db::{HirDatabase, DefDatabase}, 49 db::{HirDatabase, DefDatabase},
50 name::{AsName, KnownName}, 50 name::{AsName, KnownName},
51 source_id::SourceFileItemId, 51 source_id::{FileAstId, AstId},
52}; 52};
53 53
54pub use self::{ 54pub use self::{
55 path::{Path, PathKind}, 55 path::{Path, PathKind},
56 name::Name, 56 name::Name,
57 source_id::{SourceFileItems, SourceItemId}, 57 source_id::{AstIdMap, ErasedFileAstId},
58 ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc, HirInterner}, 58 ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc, HirInterner},
59 nameres::{PerNs, Namespace}, 59 nameres::{PerNs, Namespace},
60 ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay}, 60 ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay},
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index e962bbd31..67b9d6986 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -59,13 +59,15 @@ use rustc_hash::FxHashMap;
59use ra_arena::{Arena, RawId, impl_arena_id}; 59use ra_arena::{Arena, RawId, impl_arena_id};
60use ra_db::{FileId, Edition}; 60use ra_db::{FileId, Edition};
61use test_utils::tested_by; 61use test_utils::tested_by;
62use ra_syntax::ast;
62 63
63use crate::{ 64use crate::{
64 ModuleDef, Name, Crate, Module, SourceItemId, 65 ModuleDef, Name, Crate, Module,
65 DefDatabase, Path, PathKind, HirFileId, Trait, 66 DefDatabase, Path, PathKind, HirFileId, Trait,
66 ids::MacroDefId, 67 ids::MacroDefId,
67 diagnostics::DiagnosticSink, 68 diagnostics::DiagnosticSink,
68 nameres::diagnostics::DefDiagnostic, 69 nameres::diagnostics::DefDiagnostic,
70 AstId,
69}; 71};
70 72
71pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap}; 73pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap};
@@ -106,7 +108,7 @@ pub(crate) struct ModuleData {
106 pub(crate) children: FxHashMap<Name, CrateModuleId>, 108 pub(crate) children: FxHashMap<Name, CrateModuleId>,
107 pub(crate) scope: ModuleScope, 109 pub(crate) scope: ModuleScope,
108 /// None for root 110 /// None for root
109 pub(crate) declaration: Option<SourceItemId>, 111 pub(crate) declaration: Option<AstId<ast::Module>>,
110 /// None for inline modules. 112 /// None for inline modules.
111 /// 113 ///
112 /// Note that non-inline modules, by definition, live inside non-macro file. 114 /// Note that non-inline modules, by definition, live inside non-macro file.
@@ -225,7 +227,7 @@ impl CrateDefMap {
225 pub(crate) fn find_module_by_source( 227 pub(crate) fn find_module_by_source(
226 &self, 228 &self,
227 file_id: HirFileId, 229 file_id: HirFileId,
228 decl_id: Option<SourceItemId>, 230 decl_id: Option<AstId<ast::Module>>,
229 ) -> Option<CrateModuleId> { 231 ) -> Option<CrateModuleId> {
230 let (module_id, _module_data) = self.modules.iter().find(|(_module_id, module_data)| { 232 let (module_id, _module_data) = self.modules.iter().find(|(_module_id, module_data)| {
231 if decl_id.is_some() { 233 if decl_id.is_some() {
@@ -429,10 +431,10 @@ impl CrateDefMap {
429 431
430mod diagnostics { 432mod diagnostics {
431 use relative_path::RelativePathBuf; 433 use relative_path::RelativePathBuf;
432 use ra_syntax::{AstPtr, AstNode, ast}; 434 use ra_syntax::{AstPtr, ast};
433 435
434 use crate::{ 436 use crate::{
435 SourceItemId, DefDatabase, 437 AstId, DefDatabase,
436 nameres::CrateModuleId, 438 nameres::CrateModuleId,
437 diagnostics::{DiagnosticSink, UnresolvedModule}, 439 diagnostics::{DiagnosticSink, UnresolvedModule},
438}; 440};
@@ -441,7 +443,7 @@ mod diagnostics {
441 pub(super) enum DefDiagnostic { 443 pub(super) enum DefDiagnostic {
442 UnresolvedModule { 444 UnresolvedModule {
443 module: CrateModuleId, 445 module: CrateModuleId,
444 declaration: SourceItemId, 446 declaration: AstId<ast::Module>,
445 candidate: RelativePathBuf, 447 candidate: RelativePathBuf,
446 }, 448 },
447 } 449 }
@@ -458,10 +460,9 @@ mod diagnostics {
458 if *module != target_module { 460 if *module != target_module {
459 return; 461 return;
460 } 462 }
461 let syntax = db.file_item(*declaration); 463 let decl = declaration.to_node(db);
462 let decl = ast::Module::cast(&syntax).unwrap();
463 sink.push(UnresolvedModule { 464 sink.push(UnresolvedModule {
464 file: declaration.file_id, 465 file: declaration.file_id(),
465 decl: AstPtr::new(&decl), 466 decl: AstPtr::new(&decl),
466 candidate: candidate.clone(), 467 candidate: candidate.clone(),
467 }) 468 })
@@ -469,5 +470,4 @@ mod diagnostics {
469 } 470 }
470 } 471 }
471 } 472 }
472
473} 473}
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 4fb298155..39cadc94a 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -3,10 +3,11 @@ use rustc_hash::FxHashMap;
3use relative_path::RelativePathBuf; 3use relative_path::RelativePathBuf;
4use test_utils::tested_by; 4use test_utils::tested_by;
5use ra_db::FileId; 5use ra_db::FileId;
6use ra_syntax::ast;
6 7
7use crate::{ 8use crate::{
8 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, 9 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias,
9 DefDatabase, HirFileId, Name, Path, SourceItemId, 10 DefDatabase, HirFileId, Name, Path,
10 KnownName, 11 KnownName,
11 nameres::{ 12 nameres::{
12 Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, 13 Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode,
@@ -15,6 +16,7 @@ use crate::{
15 raw, 16 raw,
16 }, 17 },
17 ids::{AstItemDef, LocationCtx, MacroCallLoc, MacroCallId, MacroDefId}, 18 ids::{AstItemDef, LocationCtx, MacroCallLoc, MacroCallId, MacroDefId},
19 AstId,
18}; 20};
19 21
20pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { 22pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
@@ -51,7 +53,7 @@ struct DefCollector<DB> {
51 def_map: CrateDefMap, 53 def_map: CrateDefMap,
52 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, 54 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>,
53 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, 55 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>,
54 unexpanded_macros: Vec<(CrateModuleId, SourceItemId, Path)>, 56 unexpanded_macros: Vec<(CrateModuleId, AstId<ast::MacroCall>, Path)>,
55 global_macro_scope: FxHashMap<Name, MacroDefId>, 57 global_macro_scope: FxHashMap<Name, MacroDefId>,
56} 58}
57 59
@@ -293,7 +295,7 @@ where
293 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); 295 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
294 let mut resolved = Vec::new(); 296 let mut resolved = Vec::new();
295 let mut res = ReachedFixedPoint::Yes; 297 let mut res = ReachedFixedPoint::Yes;
296 macros.retain(|(module_id, source_item_id, path)| { 298 macros.retain(|(module_id, ast_id, path)| {
297 if path.segments.len() != 2 { 299 if path.segments.len() != 2 {
298 return true; 300 return true;
299 } 301 }
@@ -309,8 +311,7 @@ where
309 res = ReachedFixedPoint::No; 311 res = ReachedFixedPoint::No;
310 let def_map = self.db.crate_def_map(krate); 312 let def_map = self.db.crate_def_map(krate);
311 if let Some(macro_id) = def_map.public_macros.get(&path.segments[1].name).cloned() { 313 if let Some(macro_id) = def_map.public_macros.get(&path.segments[1].name).cloned() {
312 let call_id = 314 let call_id = MacroCallLoc { def: macro_id, ast_id: *ast_id }.id(self.db);
313 MacroCallLoc { def: macro_id, source_item_id: *source_item_id }.id(self.db);
314 resolved.push((*module_id, call_id)); 315 resolved.push((*module_id, call_id));
315 } 316 }
316 false 317 false
@@ -364,12 +365,9 @@ where
364 fn collect_module(&mut self, module: &raw::ModuleData) { 365 fn collect_module(&mut self, module: &raw::ModuleData) {
365 match module { 366 match module {
366 // inline module, just recurse 367 // inline module, just recurse
367 raw::ModuleData::Definition { name, items, source_item_id } => { 368 raw::ModuleData::Definition { name, items, ast_id } => {
368 let module_id = self.push_child_module( 369 let module_id =
369 name.clone(), 370 self.push_child_module(name.clone(), ast_id.with_file_id(self.file_id), None);
370 source_item_id.with_file_id(self.file_id),
371 None,
372 );
373 ModCollector { 371 ModCollector {
374 def_collector: &mut *self.def_collector, 372 def_collector: &mut *self.def_collector,
375 module_id, 373 module_id,
@@ -379,13 +377,12 @@ where
379 .collect(&*items); 377 .collect(&*items);
380 } 378 }
381 // out of line module, resovle, parse and recurse 379 // out of line module, resovle, parse and recurse
382 raw::ModuleData::Declaration { name, source_item_id } => { 380 raw::ModuleData::Declaration { name, ast_id } => {
383 let source_item_id = source_item_id.with_file_id(self.file_id); 381 let ast_id = ast_id.with_file_id(self.file_id);
384 let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); 382 let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none();
385 match resolve_submodule(self.def_collector.db, self.file_id, name, is_root) { 383 match resolve_submodule(self.def_collector.db, self.file_id, name, is_root) {
386 Ok(file_id) => { 384 Ok(file_id) => {
387 let module_id = 385 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
388 self.push_child_module(name.clone(), source_item_id, Some(file_id));
389 let raw_items = self.def_collector.db.raw_items(file_id.into()); 386 let raw_items = self.def_collector.db.raw_items(file_id.into());
390 ModCollector { 387 ModCollector {
391 def_collector: &mut *self.def_collector, 388 def_collector: &mut *self.def_collector,
@@ -398,7 +395,7 @@ where
398 Err(candidate) => self.def_collector.def_map.diagnostics.push( 395 Err(candidate) => self.def_collector.def_map.diagnostics.push(
399 DefDiagnostic::UnresolvedModule { 396 DefDiagnostic::UnresolvedModule {
400 module: self.module_id, 397 module: self.module_id,
401 declaration: source_item_id, 398 declaration: ast_id,
402 candidate, 399 candidate,
403 }, 400 },
404 ), 401 ),
@@ -410,7 +407,7 @@ where
410 fn push_child_module( 407 fn push_child_module(
411 &mut self, 408 &mut self,
412 name: Name, 409 name: Name,
413 declaration: SourceItemId, 410 declaration: AstId<ast::Module>,
414 definition: Option<FileId>, 411 definition: Option<FileId>,
415 ) -> CrateModuleId { 412 ) -> CrateModuleId {
416 let modules = &mut self.def_collector.def_map.modules; 413 let modules = &mut self.def_collector.def_map.modules;
@@ -432,23 +429,24 @@ where
432 fn define_def(&mut self, def: &raw::DefData) { 429 fn define_def(&mut self, def: &raw::DefData) {
433 let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id }; 430 let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id };
434 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into()); 431 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into());
435 macro_rules! id { 432
436 () => { 433 macro_rules! def {
437 AstItemDef::from_source_item_id_unchecked(ctx, def.source_item_id) 434 ($kind:ident, $ast_id:ident) => {
435 $kind { id: AstItemDef::from_ast_id(ctx, $ast_id) }.into()
438 }; 436 };
439 } 437 }
440 let name = def.name.clone(); 438 let name = def.name.clone();
441 let def: PerNs<ModuleDef> = match def.kind { 439 let def: PerNs<ModuleDef> = match def.kind {
442 raw::DefKind::Function => PerNs::values(Function { id: id!() }.into()), 440 raw::DefKind::Function(ast_id) => PerNs::values(def!(Function, ast_id)),
443 raw::DefKind::Struct => { 441 raw::DefKind::Struct(ast_id) => {
444 let s = Struct { id: id!() }.into(); 442 let s = def!(Struct, ast_id);
445 PerNs::both(s, s) 443 PerNs::both(s, s)
446 } 444 }
447 raw::DefKind::Enum => PerNs::types(Enum { id: id!() }.into()), 445 raw::DefKind::Enum(ast_id) => PerNs::types(def!(Enum, ast_id)),
448 raw::DefKind::Const => PerNs::values(Const { id: id!() }.into()), 446 raw::DefKind::Const(ast_id) => PerNs::values(def!(Const, ast_id)),
449 raw::DefKind::Static => PerNs::values(Static { id: id!() }.into()), 447 raw::DefKind::Static(ast_id) => PerNs::values(def!(Static, ast_id)),
450 raw::DefKind::Trait => PerNs::types(Trait { id: id!() }.into()), 448 raw::DefKind::Trait(ast_id) => PerNs::types(def!(Trait, ast_id)),
451 raw::DefKind::TypeAlias => PerNs::types(TypeAlias { id: id!() }.into()), 449 raw::DefKind::TypeAlias(ast_id) => PerNs::types(def!(TypeAlias, ast_id)),
452 }; 450 };
453 let resolution = Resolution { def, import: None }; 451 let resolution = Resolution { def, import: None };
454 self.def_collector.update(self.module_id, None, &[(name, resolution)]) 452 self.def_collector.update(self.module_id, None, &[(name, resolution)])
@@ -458,34 +456,27 @@ where
458 // Case 1: macro rules, define a macro in crate-global mutable scope 456 // Case 1: macro rules, define a macro in crate-global mutable scope
459 if is_macro_rules(&mac.path) { 457 if is_macro_rules(&mac.path) {
460 if let Some(name) = &mac.name { 458 if let Some(name) = &mac.name {
461 let macro_id = MacroDefId::MacroByExample { 459 let macro_id = MacroDefId(mac.ast_id.with_file_id(self.file_id));
462 source_item_id: mac.source_item_id.with_file_id(self.file_id),
463 };
464 self.def_collector.define_macro(name.clone(), macro_id, mac.export) 460 self.def_collector.define_macro(name.clone(), macro_id, mac.export)
465 } 461 }
466 return; 462 return;
467 } 463 }
468 464
469 let source_item_id = SourceItemId { file_id: self.file_id, item_id: mac.source_item_id }; 465 let ast_id = mac.ast_id.with_file_id(self.file_id);
470 466
471 // Case 2: try to expand macro_rules from this crate, triggering 467 // Case 2: try to expand macro_rules from this crate, triggering
472 // recursive item collection. 468 // recursive item collection.
473 if let Some(&macro_id) = 469 if let Some(&macro_id) =
474 mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(name)) 470 mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(name))
475 { 471 {
476 let macro_call_id = 472 let macro_call_id = MacroCallLoc { def: macro_id, ast_id }.id(self.def_collector.db);
477 MacroCallLoc { def: macro_id, source_item_id }.id(self.def_collector.db);
478 473
479 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id); 474 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id);
480 return; 475 return;
481 } 476 }
482 477
483 // Case 3: path to a macro from another crate, expand during name resolution 478 // Case 3: path to a macro from another crate, expand during name resolution
484 self.def_collector.unexpanded_macros.push(( 479 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, mac.path.clone()))
485 self.module_id,
486 source_item_id,
487 mac.path.clone(),
488 ))
489 } 480 }
490} 481}
491 482
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index f32004601..0936229ac 100644
--- a/crates/ra_hir/src/nameres/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -12,7 +12,7 @@ use ra_syntax::{
12 12
13use crate::{ 13use crate::{
14 DefDatabase, Name, AsName, Path, HirFileId, ModuleSource, 14 DefDatabase, Name, AsName, Path, HirFileId, ModuleSource,
15 SourceFileItemId, SourceFileItems, 15 AstIdMap, FileAstId,
16}; 16};
17 17
18/// `RawItems` is a set of top-level items in a file (except for impls). 18/// `RawItems` is a set of top-level items in a file (except for impls).
@@ -60,7 +60,7 @@ impl RawItems {
60 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) { 60 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) {
61 let mut collector = RawItemsCollector { 61 let mut collector = RawItemsCollector {
62 raw_items: RawItems::default(), 62 raw_items: RawItems::default(),
63 source_file_items: db.file_items(file_id.into()), 63 source_ast_id_map: db.ast_id_map(file_id.into()),
64 source_map: ImportSourceMap::default(), 64 source_map: ImportSourceMap::default(),
65 }; 65 };
66 let source_file = db.hir_parse(file_id); 66 let source_file = db.hir_parse(file_id);
@@ -115,8 +115,8 @@ impl_arena_id!(Module);
115 115
116#[derive(Debug, PartialEq, Eq)] 116#[derive(Debug, PartialEq, Eq)]
117pub(super) enum ModuleData { 117pub(super) enum ModuleData {
118 Declaration { name: Name, source_item_id: SourceFileItemId }, 118 Declaration { name: Name, ast_id: FileAstId<ast::Module> },
119 Definition { name: Name, source_item_id: SourceFileItemId, items: Vec<RawItem> }, 119 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> },
120} 120}
121 121
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -138,20 +138,19 @@ impl_arena_id!(Def);
138 138
139#[derive(Debug, PartialEq, Eq)] 139#[derive(Debug, PartialEq, Eq)]
140pub(super) struct DefData { 140pub(super) struct DefData {
141 pub(super) source_item_id: SourceFileItemId,
142 pub(super) name: Name, 141 pub(super) name: Name,
143 pub(super) kind: DefKind, 142 pub(super) kind: DefKind,
144} 143}
145 144
146#[derive(Debug, PartialEq, Eq, Clone, Copy)] 145#[derive(Debug, PartialEq, Eq, Clone, Copy)]
147pub(super) enum DefKind { 146pub(super) enum DefKind {
148 Function, 147 Function(FileAstId<ast::FnDef>),
149 Struct, 148 Struct(FileAstId<ast::StructDef>),
150 Enum, 149 Enum(FileAstId<ast::EnumDef>),
151 Const, 150 Const(FileAstId<ast::ConstDef>),
152 Static, 151 Static(FileAstId<ast::StaticDef>),
153 Trait, 152 Trait(FileAstId<ast::TraitDef>),
154 TypeAlias, 153 TypeAlias(FileAstId<ast::TypeAliasDef>),
155} 154}
156 155
157#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 156#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -160,7 +159,7 @@ impl_arena_id!(Macro);
160 159
161#[derive(Debug, PartialEq, Eq)] 160#[derive(Debug, PartialEq, Eq)]
162pub(super) struct MacroData { 161pub(super) struct MacroData {
163 pub(super) source_item_id: SourceFileItemId, 162 pub(super) ast_id: FileAstId<ast::MacroCall>,
164 pub(super) path: Path, 163 pub(super) path: Path,
165 pub(super) name: Option<Name>, 164 pub(super) name: Option<Name>,
166 pub(super) export: bool, 165 pub(super) export: bool,
@@ -168,7 +167,7 @@ pub(super) struct MacroData {
168 167
169struct RawItemsCollector { 168struct RawItemsCollector {
170 raw_items: RawItems, 169 raw_items: RawItems,
171 source_file_items: Arc<SourceFileItems>, 170 source_ast_id_map: Arc<AstIdMap>,
172 source_map: ImportSourceMap, 171 source_map: ImportSourceMap,
173} 172}
174 173
@@ -200,18 +199,31 @@ impl RawItemsCollector {
200 // impls don't participate in name resolution 199 // impls don't participate in name resolution
201 return; 200 return;
202 } 201 }
203 ast::ModuleItemKind::StructDef(it) => (DefKind::Struct, it.name()), 202 ast::ModuleItemKind::StructDef(it) => {
204 ast::ModuleItemKind::EnumDef(it) => (DefKind::Enum, it.name()), 203 (DefKind::Struct(self.source_ast_id_map.ast_id(it)), it.name())
205 ast::ModuleItemKind::FnDef(it) => (DefKind::Function, it.name()), 204 }
206 ast::ModuleItemKind::TraitDef(it) => (DefKind::Trait, it.name()), 205 ast::ModuleItemKind::EnumDef(it) => {
207 ast::ModuleItemKind::TypeAliasDef(it) => (DefKind::TypeAlias, it.name()), 206 (DefKind::Enum(self.source_ast_id_map.ast_id(it)), it.name())
208 ast::ModuleItemKind::ConstDef(it) => (DefKind::Const, it.name()), 207 }
209 ast::ModuleItemKind::StaticDef(it) => (DefKind::Static, it.name()), 208 ast::ModuleItemKind::FnDef(it) => {
209 (DefKind::Function(self.source_ast_id_map.ast_id(it)), it.name())
210 }
211 ast::ModuleItemKind::TraitDef(it) => {
212 (DefKind::Trait(self.source_ast_id_map.ast_id(it)), it.name())
213 }
214 ast::ModuleItemKind::TypeAliasDef(it) => {
215 (DefKind::TypeAlias(self.source_ast_id_map.ast_id(it)), it.name())
216 }
217 ast::ModuleItemKind::ConstDef(it) => {
218 (DefKind::Const(self.source_ast_id_map.ast_id(it)), it.name())
219 }
220 ast::ModuleItemKind::StaticDef(it) => {
221 (DefKind::Static(self.source_ast_id_map.ast_id(it)), it.name())
222 }
210 }; 223 };
211 if let Some(name) = name { 224 if let Some(name) = name {
212 let name = name.as_name(); 225 let name = name.as_name();
213 let source_item_id = self.source_file_items.id_of_unchecked(item.syntax()); 226 let def = self.raw_items.defs.alloc(DefData { name, kind });
214 let def = self.raw_items.defs.alloc(DefData { name, kind, source_item_id });
215 self.push_item(current_module, RawItem::Def(def)) 227 self.push_item(current_module, RawItem::Def(def))
216 } 228 }
217 } 229 }
@@ -221,10 +233,9 @@ impl RawItemsCollector {
221 Some(it) => it.as_name(), 233 Some(it) => it.as_name(),
222 None => return, 234 None => return,
223 }; 235 };
224 let source_item_id = self.source_file_items.id_of_unchecked(module.syntax()); 236 let ast_id = self.source_ast_id_map.ast_id(module);
225 if module.has_semi() { 237 if module.has_semi() {
226 let item = 238 let item = self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id });
227 self.raw_items.modules.alloc(ModuleData::Declaration { name, source_item_id });
228 self.push_item(current_module, RawItem::Module(item)); 239 self.push_item(current_module, RawItem::Module(item));
229 return; 240 return;
230 } 241 }
@@ -232,7 +243,7 @@ impl RawItemsCollector {
232 if let Some(item_list) = module.item_list() { 243 if let Some(item_list) = module.item_list() {
233 let item = self.raw_items.modules.alloc(ModuleData::Definition { 244 let item = self.raw_items.modules.alloc(ModuleData::Definition {
234 name, 245 name,
235 source_item_id, 246 ast_id,
236 items: Vec::new(), 247 items: Vec::new(),
237 }); 248 });
238 self.process_module(Some(item), item_list); 249 self.process_module(Some(item), item_list);
@@ -286,9 +297,9 @@ impl RawItemsCollector {
286 }; 297 };
287 298
288 let name = m.name().map(|it| it.as_name()); 299 let name = m.name().map(|it| it.as_name());
289 let source_item_id = self.source_file_items.id_of_unchecked(m.syntax()); 300 let ast_id = self.source_ast_id_map.ast_id(m);
290 let export = m.has_atom_attr("macro_export"); 301 let export = m.has_atom_attr("macro_export");
291 let m = self.raw_items.macros.alloc(MacroData { source_item_id, path, name, export }); 302 let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export });
292 self.push_item(current_module, RawItem::Macro(m)); 303 self.push_item(current_module, RawItem::Macro(m));
293 } 304 }
294 305
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index db9e3a22e..9dae4c3d1 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -13,10 +13,10 @@ use ra_syntax::{
13}; 13};
14 14
15use crate::{ 15use crate::{
16 HirDatabase, Function, Struct, Enum, SourceItemId, 16 HirDatabase, Function, Struct, Enum,
17 AsName, Module, HirFileId, Crate, Trait, Resolver, 17 AsName, Module, HirFileId, Crate, Trait, Resolver,
18 ids::LocationCtx, 18 ids::LocationCtx,
19 expr 19 expr, AstId
20}; 20};
21 21
22/// Locates the module by `FileId`. Picks topmost module in the file. 22/// Locates the module by `FileId`. Picks topmost module in the file.
@@ -54,8 +54,8 @@ fn module_from_inline(
54) -> Option<Module> { 54) -> Option<Module> {
55 assert!(!module.has_semi()); 55 assert!(!module.has_semi());
56 let file_id = file_id.into(); 56 let file_id = file_id.into();
57 let file_items = db.file_items(file_id); 57 let ast_id_map = db.ast_id_map(file_id);
58 let item_id = file_items.id_of(file_id, module.syntax()).with_file_id(file_id); 58 let item_id = ast_id_map.ast_id(module).with_file_id(file_id);
59 module_from_source(db, file_id, Some(item_id)) 59 module_from_source(db, file_id, Some(item_id))
60} 60}
61 61
@@ -75,7 +75,7 @@ pub fn module_from_child_node(
75fn module_from_source( 75fn module_from_source(
76 db: &impl HirDatabase, 76 db: &impl HirDatabase,
77 file_id: HirFileId, 77 file_id: HirFileId,
78 decl_id: Option<SourceItemId>, 78 decl_id: Option<AstId<ast::Module>>,
79) -> Option<Module> { 79) -> Option<Module> {
80 let source_root_id = db.file_source_root(file_id.as_original_file()); 80 let source_root_id = db.file_source_root(file_id.as_original_file());
81 db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map( 81 db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map(
diff --git a/crates/ra_hir/src/source_id.rs b/crates/ra_hir/src/source_id.rs
index 62707ba6a..0a8fb6d32 100644
--- a/crates/ra_hir/src/source_id.rs
+++ b/crates/ra_hir/src/source_id.rs
@@ -1,59 +1,122 @@
1use std::sync::Arc; 1use std::{marker::PhantomData, sync::Arc, hash::{Hash, Hasher}};
2 2
3use ra_arena::{Arena, RawId, impl_arena_id}; 3use ra_arena::{Arena, RawId, impl_arena_id};
4use ra_syntax::{SyntaxNodePtr, TreeArc, SyntaxNode, SourceFile, AstNode, ast}; 4use ra_syntax::{SyntaxNodePtr, TreeArc, SyntaxNode, SourceFile, AstNode, ast};
5 5
6use crate::{HirFileId, DefDatabase}; 6use crate::{HirFileId, DefDatabase};
7 7
8/// Identifier of item within a specific file. This is stable over reparses, so 8/// `AstId` points to an AST node in any file.
9/// it's OK to use it as a salsa key/value. 9///
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 10/// It is stable across reparses, and can be used as salsa key/value.
11pub(crate) struct SourceFileItemId(RawId); 11#[derive(Debug)]
12impl_arena_id!(SourceFileItemId); 12pub(crate) struct AstId<N: AstNode> {
13 file_id: HirFileId,
14 file_ast_id: FileAstId<N>,
15}
16
17impl<N: AstNode> Clone for AstId<N> {
18 fn clone(&self) -> AstId<N> {
19 *self
20 }
21}
22impl<N: AstNode> Copy for AstId<N> {}
23
24impl<N: AstNode> PartialEq for AstId<N> {
25 fn eq(&self, other: &Self) -> bool {
26 (self.file_id, self.file_ast_id) == (other.file_id, other.file_ast_id)
27 }
28}
29impl<N: AstNode> Eq for AstId<N> {}
30impl<N: AstNode> Hash for AstId<N> {
31 fn hash<H: Hasher>(&self, hasher: &mut H) {
32 (self.file_id, self.file_ast_id).hash(hasher);
33 }
34}
35
36impl<N: AstNode> AstId<N> {
37 pub(crate) fn file_id(&self) -> HirFileId {
38 self.file_id
39 }
40
41 pub(crate) fn to_node(&self, db: &impl DefDatabase) -> TreeArc<N> {
42 let syntax_node = db.ast_id_to_node(self.file_id, self.file_ast_id.raw);
43 N::cast(&syntax_node).unwrap().to_owned()
44 }
45}
46
47/// `AstId` points to an AST node in a specific file.
48#[derive(Debug)]
49pub(crate) struct FileAstId<N: AstNode> {
50 raw: ErasedFileAstId,
51 _ty: PhantomData<N>,
52}
53
54impl<N: AstNode> Clone for FileAstId<N> {
55 fn clone(&self) -> FileAstId<N> {
56 *self
57 }
58}
59impl<N: AstNode> Copy for FileAstId<N> {}
13 60
14impl SourceFileItemId { 61impl<N: AstNode> PartialEq for FileAstId<N> {
15 pub(crate) fn with_file_id(self, file_id: HirFileId) -> SourceItemId { 62 fn eq(&self, other: &Self) -> bool {
16 SourceItemId { file_id, item_id: self } 63 self.raw == other.raw
64 }
65}
66impl<N: AstNode> Eq for FileAstId<N> {}
67impl<N: AstNode> Hash for FileAstId<N> {
68 fn hash<H: Hasher>(&self, hasher: &mut H) {
69 self.raw.hash(hasher);
17 } 70 }
18} 71}
19 72
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 73impl<N: AstNode> FileAstId<N> {
21pub struct SourceItemId { 74 pub(crate) fn with_file_id(self, file_id: HirFileId) -> AstId<N> {
22 pub(crate) file_id: HirFileId, 75 AstId { file_id, file_ast_id: self }
23 pub(crate) item_id: SourceFileItemId, 76 }
24} 77}
25 78
26/// Maps items' `SyntaxNode`s to `SourceFileItemId`s and back. 79#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
80pub struct ErasedFileAstId(RawId);
81impl_arena_id!(ErasedFileAstId);
82
83/// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.
27#[derive(Debug, PartialEq, Eq)] 84#[derive(Debug, PartialEq, Eq)]
28pub struct SourceFileItems { 85pub struct AstIdMap {
29 file_id: HirFileId, 86 arena: Arena<ErasedFileAstId, SyntaxNodePtr>,
30 arena: Arena<SourceFileItemId, SyntaxNodePtr>,
31} 87}
32 88
33impl SourceFileItems { 89impl AstIdMap {
34 pub(crate) fn file_items_query( 90 pub(crate) fn ast_id_map_query(db: &impl DefDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
35 db: &impl DefDatabase,
36 file_id: HirFileId,
37 ) -> Arc<SourceFileItems> {
38 let source_file = db.hir_parse(file_id); 91 let source_file = db.hir_parse(file_id);
39 Arc::new(SourceFileItems::from_source_file(&source_file, file_id)) 92 Arc::new(AstIdMap::from_source_file(&source_file))
40 } 93 }
41 94
42 pub(crate) fn file_item_query( 95 pub(crate) fn file_item_query(
43 db: &impl DefDatabase, 96 db: &impl DefDatabase,
44 source_item_id: SourceItemId, 97 file_id: HirFileId,
98 ast_id: ErasedFileAstId,
45 ) -> TreeArc<SyntaxNode> { 99 ) -> TreeArc<SyntaxNode> {
46 let source_file = db.hir_parse(source_item_id.file_id); 100 let source_file = db.hir_parse(file_id);
47 db.file_items(source_item_id.file_id)[source_item_id.item_id] 101 db.ast_id_map(file_id).arena[ast_id].to_node(&source_file).to_owned()
48 .to_node(&source_file)
49 .to_owned()
50 } 102 }
51 103
52 pub(crate) fn from_source_file( 104 pub(crate) fn ast_id<N: AstNode>(&self, item: &N) -> FileAstId<N> {
53 source_file: &SourceFile, 105 let ptr = SyntaxNodePtr::new(item.syntax());
54 file_id: HirFileId, 106 let raw = match self.arena.iter().find(|(_id, i)| **i == ptr) {
55 ) -> SourceFileItems { 107 Some((it, _)) => it,
56 let mut res = SourceFileItems { file_id, arena: Arena::default() }; 108 None => panic!(
109 "Can't find {:?} in AstIdMap:\n{:?}",
110 item.syntax(),
111 self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
112 ),
113 };
114
115 FileAstId { raw, _ty: PhantomData }
116 }
117
118 fn from_source_file(source_file: &SourceFile) -> AstIdMap {
119 let mut res = AstIdMap { arena: Arena::default() };
57 // By walking the tree in bread-first order we make sure that parents 120 // By walking the tree in bread-first order we make sure that parents
58 // get lower ids then children. That is, adding a new child does not 121 // get lower ids then children. That is, adding a new child does not
59 // change parent's id. This means that, say, adding a new function to a 122 // change parent's id. This means that, say, adding a new function to a
@@ -68,35 +131,9 @@ impl SourceFileItems {
68 res 131 res
69 } 132 }
70 133
71 fn alloc(&mut self, item: &SyntaxNode) -> SourceFileItemId { 134 fn alloc(&mut self, item: &SyntaxNode) -> ErasedFileAstId {
72 self.arena.alloc(SyntaxNodePtr::new(item)) 135 self.arena.alloc(SyntaxNodePtr::new(item))
73 } 136 }
74 pub(crate) fn id_of(&self, file_id: HirFileId, item: &SyntaxNode) -> SourceFileItemId {
75 assert_eq!(
76 self.file_id, file_id,
77 "SourceFileItems: wrong file, expected {:?}, got {:?}",
78 self.file_id, file_id
79 );
80 self.id_of_unchecked(item)
81 }
82 pub(crate) fn id_of_unchecked(&self, item: &SyntaxNode) -> SourceFileItemId {
83 let ptr = SyntaxNodePtr::new(item);
84 if let Some((id, _)) = self.arena.iter().find(|(_id, i)| **i == ptr) {
85 return id;
86 }
87 panic!(
88 "Can't find {:?} in SourceFileItems:\n{:?}",
89 item,
90 self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
91 );
92 }
93}
94
95impl std::ops::Index<SourceFileItemId> for SourceFileItems {
96 type Output = SyntaxNodePtr;
97 fn index(&self, idx: SourceFileItemId) -> &SyntaxNodePtr {
98 &self.arena[idx]
99 }
100} 137}
101 138
102/// Walks the subtree in bfs order, calling `f` for each node. 139/// Walks the subtree in bfs order, calling `f` for each node.