aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/attr.rs108
-rw-r--r--crates/ra_hir_def/src/body.rs3
-rw-r--r--crates/ra_hir_def/src/data.rs2
-rw-r--r--crates/ra_hir_def/src/db.rs5
-rw-r--r--crates/ra_hir_def/src/docs.rs2
-rw-r--r--crates/ra_hir_def/src/lang_item.rs4
-rw-r--r--crates/ra_hir_def/src/lib.rs67
-rw-r--r--crates/ra_hir_def/src/nameres.rs35
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs61
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs7
-rw-r--r--crates/ra_hir_def/src/resolver.rs2
11 files changed, 146 insertions, 150 deletions
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 48ce8cd93..53456fc08 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -2,9 +2,8 @@
2 2
3use std::{ops, sync::Arc}; 3use std::{ops, sync::Arc};
4 4
5use hir_expand::{either::Either, hygiene::Hygiene, AstId}; 5use hir_expand::{either::Either, hygiene::Hygiene, AstId, Source};
6use mbe::ast_to_token_tree; 6use mbe::ast_to_token_tree;
7use ra_cfg::CfgOptions;
8use ra_syntax::{ 7use ra_syntax::{
9 ast::{self, AstNode, AttrsOwner}, 8 ast::{self, AstNode, AttrsOwner},
10 SmolStr, 9 SmolStr,
@@ -40,50 +39,53 @@ impl Attrs {
40 Some(it) => it, 39 Some(it) => it,
41 None => return Attrs::default(), 40 None => return Attrs::default(),
42 }; 41 };
43 let hygiene = Hygiene::new(db, src.file_id); 42 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
44 Attr::from_attrs_owner(&src.value, &hygiene)
45 } 43 }
46 AttrDefId::StructFieldId(it) => { 44 AttrDefId::StructFieldId(it) => {
47 let src = it.parent.child_source(db); 45 let src = it.parent.child_source(db);
48 match &src.value[it.local_id] { 46 match &src.value[it.local_id] {
49 Either::A(_tuple) => Attrs::default(), 47 Either::A(_tuple) => Attrs::default(),
50 Either::B(record) => { 48 Either::B(record) => Attrs::from_attrs_owner(db, src.with_value(record)),
51 let hygiene = Hygiene::new(db, src.file_id);
52 Attr::from_attrs_owner(record, &hygiene)
53 }
54 } 49 }
55 } 50 }
56 AttrDefId::EnumVariantId(it) => { 51 AttrDefId::EnumVariantId(var_id) => {
57 let src = it.parent.child_source(db); 52 let src = var_id.parent.child_source(db);
58 let hygiene = Hygiene::new(db, src.file_id); 53 let src = src.as_ref().map(|it| &it[var_id.local_id]);
59 Attr::from_attrs_owner(&src.value[it.local_id], &hygiene) 54 Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
60 } 55 }
61 AttrDefId::AdtId(it) => match it { 56 AttrDefId::AdtId(it) => match it {
62 AdtId::StructId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db), 57 AdtId::StructId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db),
63 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 58 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
64 AdtId::UnionId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db), 59 AdtId::UnionId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db),
65 }, 60 },
66 AttrDefId::StaticId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
67 AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 61 AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
68 AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db), 62 AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db),
69 AttrDefId::ImplId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 63 AttrDefId::ImplId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
70 AttrDefId::ConstId(it) => attrs_from_loc(it.lookup(db), db), 64 AttrDefId::ConstId(it) => attrs_from_loc(it.lookup(db), db),
65 AttrDefId::StaticId(it) => attrs_from_loc(it.lookup(db), db),
71 AttrDefId::FunctionId(it) => attrs_from_loc(it.lookup(db), db), 66 AttrDefId::FunctionId(it) => attrs_from_loc(it.lookup(db), db),
72 AttrDefId::TypeAliasId(it) => attrs_from_loc(it.lookup(db), db), 67 AttrDefId::TypeAliasId(it) => attrs_from_loc(it.lookup(db), db),
73 } 68 }
74 } 69 }
75 70
76 pub fn has_atom(&self, atom: &str) -> bool { 71 fn from_attrs_owner(db: &impl DefDatabase, owner: Source<&dyn AttrsOwner>) -> Attrs {
77 self.iter().any(|it| it.is_simple_atom(atom)) 72 let hygiene = Hygiene::new(db, owner.file_id);
73 Attrs::new(owner.value, &hygiene)
78 } 74 }
79 75
80 pub fn find_string_value(&self, key: &str) -> Option<SmolStr> { 76 pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs {
81 self.iter().filter(|attr| attr.is_simple_atom(key)).find_map(|attr| { 77 let mut attrs = owner.attrs().peekable();
82 match attr.input.as_ref()? { 78 let entries = if attrs.peek().is_none() {
83 AttrInput::Literal(it) => Some(it.clone()), 79 // Avoid heap allocation
84 _ => None, 80 None
85 } 81 } else {
86 }) 82 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect())
83 };
84 Attrs { entries }
85 }
86
87 pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
88 AttrQuery { attrs: self, key }
87 } 89 }
88} 90}
89 91
@@ -100,7 +102,7 @@ pub enum AttrInput {
100} 102}
101 103
102impl Attr { 104impl Attr {
103 pub(crate) fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> { 105 fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> {
104 let path = Path::from_src(ast.path()?, hygiene)?; 106 let path = Path::from_src(ast.path()?, hygiene)?;
105 let input = match ast.input() { 107 let input = match ast.input() {
106 None => None, 108 None => None,
@@ -116,46 +118,37 @@ impl Attr {
116 118
117 Some(Attr { path, input }) 119 Some(Attr { path, input })
118 } 120 }
121}
119 122
120 pub fn from_attrs_owner(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs { 123pub struct AttrQuery<'a> {
121 let mut attrs = owner.attrs().peekable(); 124 attrs: &'a Attrs,
122 let entries = if attrs.peek().is_none() { 125 key: &'static str,
123 // Avoid heap allocation 126}
124 None
125 } else {
126 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect())
127 };
128 Attrs { entries }
129 }
130 127
131 pub fn is_simple_atom(&self, name: &str) -> bool { 128impl<'a> AttrQuery<'a> {
132 // FIXME: Avoid cloning 129 pub fn tt_values(self) -> impl Iterator<Item = &'a Subtree> {
133 self.path.as_ident().map_or(false, |s| s.to_string() == name) 130 self.attrs().filter_map(|attr| match attr.input.as_ref()? {
131 AttrInput::TokenTree(it) => Some(it),
132 _ => None,
133 })
134 } 134 }
135 135
136 // FIXME: handle cfg_attr :-) 136 pub fn string_value(self) -> Option<&'a SmolStr> {
137 pub fn as_cfg(&self) -> Option<&Subtree> { 137 self.attrs().find_map(|attr| match attr.input.as_ref()? {
138 if !self.is_simple_atom("cfg") { 138 AttrInput::Literal(it) => Some(it),
139 return None;
140 }
141 match &self.input {
142 Some(AttrInput::TokenTree(subtree)) => Some(subtree),
143 _ => None, 139 _ => None,
144 } 140 })
145 } 141 }
146 142
147 pub fn as_path(&self) -> Option<&SmolStr> { 143 pub fn exists(self) -> bool {
148 if !self.is_simple_atom("path") { 144 self.attrs().next().is_some()
149 return None;
150 }
151 match &self.input {
152 Some(AttrInput::Literal(it)) => Some(it),
153 _ => None,
154 }
155 } 145 }
156 146
157 pub fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> Option<bool> { 147 fn attrs(self) -> impl Iterator<Item = &'a Attr> {
158 cfg_options.is_cfg_enabled(self.as_cfg()?) 148 let key = self.key;
149 self.attrs
150 .iter()
151 .filter(move |attr| attr.path.as_ident().map_or(false, |s| s.to_string() == key))
159 } 152 }
160} 153}
161 154
@@ -164,8 +157,8 @@ where
164 N: ast::AttrsOwner, 157 N: ast::AttrsOwner,
165 D: DefDatabase, 158 D: DefDatabase,
166{ 159{
167 let hygiene = Hygiene::new(db, src.file_id()); 160 let src = Source::new(src.file_id(), src.to_node(db));
168 Attr::from_attrs_owner(&src.to_node(db), &hygiene) 161 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
169} 162}
170 163
171fn attrs_from_loc<T, D>(node: T, db: &D) -> Attrs 164fn attrs_from_loc<T, D>(node: T, db: &D) -> Attrs
@@ -175,6 +168,5 @@ where
175 D: DefDatabase, 168 D: DefDatabase,
176{ 169{
177 let src = node.source(db); 170 let src = node.source(db);
178 let hygiene = Hygiene::new(db, src.file_id); 171 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
179 Attr::from_attrs_owner(&src.value, &hygiene)
180} 172}
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 225638b42..1589085b5 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -17,7 +17,7 @@ use crate::{
17 expr::{Expr, ExprId, Pat, PatId}, 17 expr::{Expr, ExprId, Pat, PatId},
18 nameres::CrateDefMap, 18 nameres::CrateDefMap,
19 path::Path, 19 path::Path,
20 AstItemDef, DefWithBodyId, HasModule, HasSource, Lookup, ModuleId, 20 DefWithBodyId, HasModule, HasSource, Lookup, ModuleId,
21}; 21};
22 22
23pub struct Expander { 23pub struct Expander {
@@ -160,6 +160,7 @@ impl Body {
160 (src.file_id, c.module(db), src.value.body()) 160 (src.file_id, c.module(db), src.value.body())
161 } 161 }
162 DefWithBodyId::StaticId(s) => { 162 DefWithBodyId::StaticId(s) => {
163 let s = s.lookup(db);
163 let src = s.source(db); 164 let src = s.source(db);
164 (src.file_id, s.module(db), src.value.body()) 165 (src.file_id, s.module(db), src.value.body())
165 } 166 }
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index f0b3e198a..81a8ec18d 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -204,7 +204,7 @@ impl ConstData {
204 } 204 }
205 205
206 pub(crate) fn static_data_query(db: &impl DefDatabase, konst: StaticId) -> Arc<ConstData> { 206 pub(crate) fn static_data_query(db: &impl DefDatabase, konst: StaticId) -> Arc<ConstData> {
207 let node = konst.source(db).value; 207 let node = konst.lookup(db).source(db).value;
208 const_data_for(&node) 208 const_data_for(&node)
209 } 209 }
210} 210}
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 7fec2e8c0..32adb11bd 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -18,7 +18,8 @@ use crate::{
18 CrateDefMap, 18 CrateDefMap,
19 }, 19 },
20 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId, 20 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId,
21 ImplId, ItemLoc, ModuleId, StaticId, StructOrUnionId, TraitId, TypeAliasId, TypeAliasLoc, 21 ImplId, ItemLoc, ModuleId, StaticId, StaticLoc, StructOrUnionId, TraitId, TypeAliasId,
22 TypeAliasLoc,
22}; 23};
23 24
24#[salsa::query_group(InternDatabaseStorage)] 25#[salsa::query_group(InternDatabaseStorage)]
@@ -32,7 +33,7 @@ pub trait InternDatabase: SourceDatabase {
32 #[salsa::interned] 33 #[salsa::interned]
33 fn intern_const(&self, loc: ConstLoc) -> ConstId; 34 fn intern_const(&self, loc: ConstLoc) -> ConstId;
34 #[salsa::interned] 35 #[salsa::interned]
35 fn intern_static(&self, loc: ItemLoc<ast::StaticDef>) -> StaticId; 36 fn intern_static(&self, loc: StaticLoc) -> StaticId;
36 #[salsa::interned] 37 #[salsa::interned]
37 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> TraitId; 38 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> TraitId;
38 #[salsa::interned] 39 #[salsa::interned]
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
index 69846fd1b..225511428 100644
--- a/crates/ra_hir_def/src/docs.rs
+++ b/crates/ra_hir_def/src/docs.rs
@@ -52,10 +52,10 @@ impl Documentation {
52 let src = it.parent.child_source(db); 52 let src = it.parent.child_source(db);
53 docs_from_ast(&src.value[it.local_id]) 53 docs_from_ast(&src.value[it.local_id])
54 } 54 }
55 AttrDefId::StaticId(it) => docs_from_ast(&it.source(db).value),
56 AttrDefId::TraitId(it) => docs_from_ast(&it.source(db).value), 55 AttrDefId::TraitId(it) => docs_from_ast(&it.source(db).value),
57 AttrDefId::MacroDefId(it) => docs_from_ast(&it.ast_id.to_node(db)), 56 AttrDefId::MacroDefId(it) => docs_from_ast(&it.ast_id.to_node(db)),
58 AttrDefId::ConstId(it) => docs_from_ast(&it.lookup(db).source(db).value), 57 AttrDefId::ConstId(it) => docs_from_ast(&it.lookup(db).source(db).value),
58 AttrDefId::StaticId(it) => docs_from_ast(&it.lookup(db).source(db).value),
59 AttrDefId::FunctionId(it) => docs_from_ast(&it.lookup(db).source(db).value), 59 AttrDefId::FunctionId(it) => docs_from_ast(&it.lookup(db).source(db).value),
60 AttrDefId::TypeAliasId(it) => docs_from_ast(&it.lookup(db).source(db).value), 60 AttrDefId::TypeAliasId(it) => docs_from_ast(&it.lookup(db).source(db).value),
61 AttrDefId::ImplId(_) => None, 61 AttrDefId::ImplId(_) => None,
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
index df951c533..3b9fb0328 100644
--- a/crates/ra_hir_def/src/lang_item.rs
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -113,8 +113,8 @@ impl LangItems {
113 T: Into<AttrDefId> + Copy, 113 T: Into<AttrDefId> + Copy,
114 { 114 {
115 let attrs = db.attrs(item.into()); 115 let attrs = db.attrs(item.into());
116 if let Some(lang_item_name) = attrs.find_string_value("lang") { 116 if let Some(lang_item_name) = attrs.by_key("lang").string_value() {
117 self.items.entry(lang_item_name).or_insert_with(|| constructor(item)); 117 self.items.entry(lang_item_name.clone()).or_insert_with(|| constructor(item));
118 } 118 }
119 } 119 }
120} 120}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 1d195d65d..f60feb5fa 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -35,7 +35,7 @@ use std::hash::{Hash, Hasher};
35 35
36use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, MacroDefId, Source}; 36use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, MacroDefId, Source};
37use ra_arena::{impl_arena_id, map::ArenaMap, RawId}; 37use ra_arena::{impl_arena_id, map::ArenaMap, RawId};
38use ra_db::{salsa, CrateId}; 38use ra_db::{impl_intern_key, salsa, CrateId};
39use ra_syntax::{ast, AstNode}; 39use ra_syntax::{ast, AstNode};
40 40
41use crate::{builtin_type::BuiltinType, db::InternDatabase}; 41use crate::{builtin_type::BuiltinType, db::InternDatabase};
@@ -56,19 +56,6 @@ pub struct ModuleId {
56pub struct LocalModuleId(RawId); 56pub struct LocalModuleId(RawId);
57impl_arena_id!(LocalModuleId); 57impl_arena_id!(LocalModuleId);
58 58
59macro_rules! impl_intern_key {
60 ($name:ident) => {
61 impl salsa::InternKey for $name {
62 fn from_intern_id(v: salsa::InternId) -> Self {
63 $name(v)
64 }
65 fn as_intern_id(&self) -> salsa::InternId {
66 self.0
67 }
68 }
69 };
70}
71
72#[derive(Debug)] 59#[derive(Debug)]
73pub struct ItemLoc<N: AstNode> { 60pub struct ItemLoc<N: AstNode> {
74 pub(crate) module: ModuleId, 61 pub(crate) module: ModuleId,
@@ -107,25 +94,10 @@ impl<'a, DB> LocationCtx<&'a DB> {
107 } 94 }
108} 95}
109 96
110impl<'a, DB: AstDatabase + InternDatabase> LocationCtx<&'a DB> {
111 pub fn to_def<N, DEF>(self, ast: &N) -> DEF
112 where
113 N: AstNode,
114 DEF: AstItemDef<N>,
115 {
116 DEF::from_ast(self, ast)
117 }
118}
119
120pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone { 97pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
121 fn intern(db: &impl InternDatabase, loc: ItemLoc<N>) -> Self; 98 fn intern(db: &impl InternDatabase, loc: ItemLoc<N>) -> Self;
122 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<N>; 99 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<N>;
123 100
124 fn from_ast(ctx: LocationCtx<&(impl AstDatabase + InternDatabase)>, ast: &N) -> Self {
125 let items = ctx.db.ast_id_map(ctx.file_id);
126 let item_id = items.ast_id(ast);
127 Self::from_ast_id(ctx, item_id)
128 }
129 fn from_ast_id(ctx: LocationCtx<&impl InternDatabase>, ast_id: FileAstId<N>) -> Self { 101 fn from_ast_id(ctx: LocationCtx<&impl InternDatabase>, ast_id: FileAstId<N>) -> Self {
130 let loc = ItemLoc { module: ctx.module, ast_id: AstId::new(ctx.file_id, ast_id) }; 102 let loc = ItemLoc { module: ctx.module, ast_id: AstId::new(ctx.file_id, ast_id) };
131 Self::intern(ctx.db, loc) 103 Self::intern(ctx.db, loc)
@@ -258,12 +230,24 @@ impl Lookup for ConstId {
258#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 230#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
259pub struct StaticId(salsa::InternId); 231pub struct StaticId(salsa::InternId);
260impl_intern_key!(StaticId); 232impl_intern_key!(StaticId);
261impl AstItemDef<ast::StaticDef> for StaticId { 233
262 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StaticDef>) -> Self { 234#[derive(Debug, Clone, PartialEq, Eq, Hash)]
263 db.intern_static(loc) 235pub struct StaticLoc {
236 pub container: ModuleId,
237 pub ast_id: AstId<ast::StaticDef>,
238}
239
240impl Intern for StaticLoc {
241 type ID = StaticId;
242 fn intern(self, db: &impl db::DefDatabase) -> StaticId {
243 db.intern_static(self)
264 } 244 }
265 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StaticDef> { 245}
266 db.lookup_intern_static(self) 246
247impl Lookup for StaticId {
248 type Data = StaticLoc;
249 fn lookup(&self, db: &impl db::DefDatabase) -> StaticLoc {
250 db.lookup_intern_static(*self)
267 } 251 }
268} 252}
269 253
@@ -494,6 +478,12 @@ impl HasModule for ConstLoc {
494 } 478 }
495} 479}
496 480
481impl HasModule for StaticLoc {
482 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId {
483 self.container
484 }
485}
486
497pub trait HasSource { 487pub trait HasSource {
498 type Value; 488 type Value;
499 fn source(&self, db: &impl db::DefDatabase) -> Source<Self::Value>; 489 fn source(&self, db: &impl db::DefDatabase) -> Source<Self::Value>;
@@ -526,6 +516,15 @@ impl HasSource for ConstLoc {
526 } 516 }
527} 517}
528 518
519impl HasSource for StaticLoc {
520 type Value = ast::StaticDef;
521
522 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::StaticDef> {
523 let node = self.ast_id.to_node(db);
524 Source::new(self.ast_id.file_id(), node)
525 }
526}
527
529pub trait HasChildSource { 528pub trait HasChildSource {
530 type ChildId; 529 type ChildId;
531 type Value; 530 type Value;
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index 3b2e99647..f6cf59c5f 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -66,7 +66,7 @@ use ra_arena::Arena;
66use ra_db::{CrateId, Edition, FileId}; 66use ra_db::{CrateId, Edition, FileId};
67use ra_prof::profile; 67use ra_prof::profile;
68use ra_syntax::ast; 68use ra_syntax::ast;
69use rustc_hash::{FxHashMap, FxHashSet}; 69use rustc_hash::FxHashMap;
70 70
71use crate::{ 71use crate::{
72 builtin_type::BuiltinType, 72 builtin_type::BuiltinType,
@@ -90,18 +90,6 @@ pub struct CrateDefMap {
90 root: LocalModuleId, 90 root: LocalModuleId,
91 modules: Arena<LocalModuleId, ModuleData>, 91 modules: Arena<LocalModuleId, ModuleData>,
92 92
93 /// Some macros are not well-behavior, which leads to infinite loop
94 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } }
95 /// We mark it down and skip it in collector
96 ///
97 /// FIXME:
98 /// Right now it only handle a poison macro in a single crate,
99 /// such that if other crate try to call that macro,
100 /// the whole process will do again until it became poisoned in that crate.
101 /// We should handle this macro set globally
102 /// However, do we want to put it as a global variable?
103 poison_macros: FxHashSet<MacroDefId>,
104
105 diagnostics: Vec<DefDiagnostic>, 93 diagnostics: Vec<DefDiagnostic>,
106} 94}
107 95
@@ -234,7 +222,6 @@ impl CrateDefMap {
234 prelude: None, 222 prelude: None,
235 root, 223 root,
236 modules, 224 modules,
237 poison_macros: FxHashSet::default(),
238 diagnostics: Vec::new(), 225 diagnostics: Vec::new(),
239 } 226 }
240 }; 227 };
@@ -267,16 +254,6 @@ impl CrateDefMap {
267 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink)) 254 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
268 } 255 }
269 256
270 pub fn resolve_path(
271 &self,
272 db: &impl DefDatabase,
273 original_module: LocalModuleId,
274 path: &Path,
275 ) -> (PerNs, Option<usize>) {
276 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
277 (res.resolved_def, res.segment_index)
278 }
279
280 pub fn modules(&self) -> impl Iterator<Item = LocalModuleId> + '_ { 257 pub fn modules(&self) -> impl Iterator<Item = LocalModuleId> + '_ {
281 self.modules.iter().map(|(id, _data)| id) 258 self.modules.iter().map(|(id, _data)| id)
282 } 259 }
@@ -287,6 +264,16 @@ impl CrateDefMap {
287 .filter(move |(_id, data)| data.definition == Some(file_id)) 264 .filter(move |(_id, data)| data.definition == Some(file_id))
288 .map(|(id, _data)| id) 265 .map(|(id, _data)| id)
289 } 266 }
267
268 pub(crate) fn resolve_path(
269 &self,
270 db: &impl DefDatabase,
271 original_module: LocalModuleId,
272 path: &Path,
273 ) -> (PerNs, Option<usize>) {
274 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
275 (res.resolved_def, res.segment_index)
276 }
290} 277}
291 278
292impl ModuleData { 279impl ModuleData {
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index b02364e86..7a5f90327 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -7,8 +7,8 @@ use hir_expand::{
7}; 7};
8use ra_cfg::CfgOptions; 8use ra_cfg::CfgOptions;
9use ra_db::{CrateId, FileId}; 9use ra_db::{CrateId, FileId};
10use ra_syntax::{ast, SmolStr}; 10use ra_syntax::ast;
11use rustc_hash::FxHashMap; 11use rustc_hash::{FxHashMap, FxHashSet};
12use test_utils::tested_by; 12use test_utils::tested_by;
13 13
14use crate::{ 14use crate::{
@@ -21,7 +21,7 @@ use crate::{
21 path::{Path, PathKind}, 21 path::{Path, PathKind},
22 per_ns::PerNs, 22 per_ns::PerNs,
23 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId, 23 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId,
24 Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, 24 Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId,
25 StructOrUnionId, TraitId, TypeAliasLoc, UnionId, 25 StructOrUnionId, TraitId, TypeAliasLoc, UnionId,
26}; 26};
27 27
@@ -57,6 +57,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C
57 unexpanded_macros: Vec::new(), 57 unexpanded_macros: Vec::new(),
58 mod_dirs: FxHashMap::default(), 58 mod_dirs: FxHashMap::default(),
59 macro_stack_monitor: MacroStackMonitor::default(), 59 macro_stack_monitor: MacroStackMonitor::default(),
60 poison_macros: FxHashSet::default(),
60 cfg_options, 61 cfg_options,
61 }; 62 };
62 collector.collect(); 63 collector.collect();
@@ -103,6 +104,17 @@ struct DefCollector<'a, DB> {
103 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly 104 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
104 /// To prevent stack overflow, we add a deep counter here for prevent that. 105 /// To prevent stack overflow, we add a deep counter here for prevent that.
105 macro_stack_monitor: MacroStackMonitor, 106 macro_stack_monitor: MacroStackMonitor,
107 /// Some macros are not well-behavior, which leads to infinite loop
108 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } }
109 /// We mark it down and skip it in collector
110 ///
111 /// FIXME:
112 /// Right now it only handle a poison macro in a single crate,
113 /// such that if other crate try to call that macro,
114 /// the whole process will do again until it became poisoned in that crate.
115 /// We should handle this macro set globally
116 /// However, do we want to put it as a global variable?
117 poison_macros: FxHashSet<MacroDefId>,
106 118
107 cfg_options: &'a CfgOptions, 119 cfg_options: &'a CfgOptions,
108} 120}
@@ -489,7 +501,7 @@ where
489 macro_call_id: MacroCallId, 501 macro_call_id: MacroCallId,
490 macro_def_id: MacroDefId, 502 macro_def_id: MacroDefId,
491 ) { 503 ) {
492 if self.def_map.poison_macros.contains(&macro_def_id) { 504 if self.poison_macros.contains(&macro_def_id) {
493 return; 505 return;
494 } 506 }
495 507
@@ -509,7 +521,7 @@ where
509 .collect(raw_items.items()); 521 .collect(raw_items.items());
510 } else { 522 } else {
511 log::error!("Too deep macro expansion: {:?}", macro_call_id); 523 log::error!("Too deep macro expansion: {:?}", macro_call_id);
512 self.def_map.poison_macros.insert(macro_def_id); 524 self.poison_macros.insert(macro_def_id);
513 } 525 }
514 526
515 self.macro_stack_monitor.decrease(macro_def_id); 527 self.macro_stack_monitor.decrease(macro_def_id);
@@ -587,8 +599,8 @@ where
587 } 599 }
588 600
589 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) { 601 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) {
590 let path_attr = self.path_attr(attrs); 602 let path_attr = attrs.by_key("path").string_value();
591 let is_macro_use = attrs.has_atom("macro_use"); 603 let is_macro_use = attrs.by_key("macro_use").exists();
592 match module { 604 match module {
593 // inline module, just recurse 605 // inline module, just recurse
594 raw::ModuleData::Definition { name, items, ast_id } => { 606 raw::ModuleData::Definition { name, items, ast_id } => {
@@ -703,7 +715,10 @@ where
703 PerNs::values(def.into()) 715 PerNs::values(def.into())
704 } 716 }
705 raw::DefKind::Static(ast_id) => { 717 raw::DefKind::Static(ast_id) => {
706 PerNs::values(StaticId::from_ast_id(ctx, ast_id).into()) 718 let def = StaticLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) }
719 .intern(self.def_collector.db);
720
721 PerNs::values(def.into())
707 } 722 }
708 raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()), 723 raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()),
709 raw::DefKind::TypeAlias(ast_id) => { 724 raw::DefKind::TypeAlias(ast_id) => {
@@ -781,11 +796,11 @@ where
781 } 796 }
782 797
783 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { 798 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
784 attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false)) 799 // FIXME: handle cfg_attr :-)
785 } 800 attrs
786 801 .by_key("cfg")
787 fn path_attr<'a>(&self, attrs: &'a Attrs) -> Option<&'a SmolStr> { 802 .tt_values()
788 attrs.iter().find_map(|attr| attr.as_path()) 803 .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false))
789 } 804 }
790} 805}
791 806
@@ -807,7 +822,7 @@ mod tests {
807 db: &impl DefDatabase, 822 db: &impl DefDatabase,
808 def_map: CrateDefMap, 823 def_map: CrateDefMap,
809 monitor: MacroStackMonitor, 824 monitor: MacroStackMonitor,
810 ) -> CrateDefMap { 825 ) -> (CrateDefMap, FxHashSet<MacroDefId>) {
811 let mut collector = DefCollector { 826 let mut collector = DefCollector {
812 db, 827 db,
813 def_map, 828 def_map,
@@ -816,13 +831,18 @@ mod tests {
816 unexpanded_macros: Vec::new(), 831 unexpanded_macros: Vec::new(),
817 mod_dirs: FxHashMap::default(), 832 mod_dirs: FxHashMap::default(),
818 macro_stack_monitor: monitor, 833 macro_stack_monitor: monitor,
834 poison_macros: FxHashSet::default(),
819 cfg_options: &CfgOptions::default(), 835 cfg_options: &CfgOptions::default(),
820 }; 836 };
821 collector.collect(); 837 collector.collect();
822 collector.finish() 838 (collector.def_map, collector.poison_macros)
823 } 839 }
824 840
825 fn do_limited_resolve(code: &str, limit: u32, poison_limit: u32) -> CrateDefMap { 841 fn do_limited_resolve(
842 code: &str,
843 limit: u32,
844 poison_limit: u32,
845 ) -> (CrateDefMap, FxHashSet<MacroDefId>) {
826 let (db, _file_id) = TestDB::with_single_file(&code); 846 let (db, _file_id) = TestDB::with_single_file(&code);
827 let krate = db.test_crate(); 847 let krate = db.test_crate();
828 848
@@ -837,7 +857,6 @@ mod tests {
837 prelude: None, 857 prelude: None,
838 root, 858 root,
839 modules, 859 modules,
840 poison_macros: FxHashSet::default(),
841 diagnostics: Vec::new(), 860 diagnostics: Vec::new(),
842 } 861 }
843 }; 862 };
@@ -867,7 +886,7 @@ foo!(KABOOM);
867 886
868 #[test] 887 #[test]
869 fn test_macro_expand_poisoned() { 888 fn test_macro_expand_poisoned() {
870 let def = do_limited_resolve( 889 let (_, poison_macros) = do_limited_resolve(
871 r#" 890 r#"
872 macro_rules! foo { 891 macro_rules! foo {
873 ($ty:ty) => { foo!($ty); } 892 ($ty:ty) => { foo!($ty); }
@@ -878,12 +897,12 @@ foo!(KABOOM);
878 16, 897 16,
879 ); 898 );
880 899
881 assert_eq!(def.poison_macros.len(), 1); 900 assert_eq!(poison_macros.len(), 1);
882 } 901 }
883 902
884 #[test] 903 #[test]
885 fn test_macro_expand_normal() { 904 fn test_macro_expand_normal() {
886 let def = do_limited_resolve( 905 let (_, poison_macros) = do_limited_resolve(
887 r#" 906 r#"
888 macro_rules! foo { 907 macro_rules! foo {
889 ($ident:ident) => { struct $ident {} } 908 ($ident:ident) => { struct $ident {} }
@@ -894,6 +913,6 @@ foo!(Bar);
894 16, 913 16,
895 ); 914 );
896 915
897 assert_eq!(def.poison_macros.len(), 0); 916 assert_eq!(poison_macros.len(), 0);
898 } 917 }
899} 918}
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 552cbe544..198578753 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -17,10 +17,7 @@ use ra_syntax::{
17use test_utils::tested_by; 17use test_utils::tested_by;
18 18
19use crate::{ 19use crate::{
20 attr::{Attr, Attrs}, 20 attr::Attrs, db::DefDatabase, path::Path, FileAstId, HirFileId, LocalImportId, Source,
21 db::DefDatabase,
22 path::Path,
23 FileAstId, HirFileId, LocalImportId, Source,
24}; 21};
25 22
26/// `RawItems` is a set of top-level items in a file (except for impls). 23/// `RawItems` is a set of top-level items in a file (except for impls).
@@ -407,6 +404,6 @@ impl RawItemsCollector {
407 } 404 }
408 405
409 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { 406 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
410 Attr::from_attrs_owner(item, &self.hygiene) 407 Attrs::new(item, &self.hygiene)
411 } 408 }
412} 409}
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index b56de44dd..4ff0a091b 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -540,7 +540,7 @@ impl HasResolver for ConstId {
540 540
541impl HasResolver for StaticId { 541impl HasResolver for StaticId {
542 fn resolver(self, db: &impl DefDatabase) -> Resolver { 542 fn resolver(self, db: &impl DefDatabase) -> Resolver {
543 self.module(db).resolver(db) 543 self.lookup(db).container.resolver(db)
544 } 544 }
545} 545}
546 546