aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-11-24 13:05:25 +0000
committerGitHub <[email protected]>2019-11-24 13:05:25 +0000
commit450b820b7069f6ed5306ef6896263e2620314b73 (patch)
tree1d4d51e200305e5adee78b28a0f86343d3bab0fd
parent982a32aca317deb91ae03346cbc7880bd7d4429b (diff)
parent4b74fb1d896ce5a1c8c4c4bf73ad2940fb86abc5 (diff)
Merge #2384
2384: Nicer API for attrs r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
-rw-r--r--crates/ra_hir/src/code_model.rs2
-rw-r--r--crates/ra_hir/src/code_model/src.rs2
-rw-r--r--crates/ra_hir/src/from_source.rs19
-rw-r--r--crates/ra_hir/src/source_binder.rs12
-rw-r--r--crates/ra_hir/src/ty/tests.rs2
-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.rs52
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs23
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs7
-rw-r--r--crates/ra_hir_def/src/resolver.rs2
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs2
16 files changed, 130 insertions, 117 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 36ea8d8bf..905bb5bcb 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -734,7 +734,7 @@ pub struct Static {
734 734
735impl Static { 735impl Static {
736 pub fn module(self, db: &impl DefDatabase) -> Module { 736 pub fn module(self, db: &impl DefDatabase) -> Module {
737 Module { id: self.id.module(db) } 737 Module { id: self.id.lookup(db).module(db) }
738 } 738 }
739 739
740 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 740 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index 59cda2e89..b9d21bdd7 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -88,7 +88,7 @@ impl HasSource for Const {
88impl HasSource for Static { 88impl HasSource for Static {
89 type Ast = ast::StaticDef; 89 type Ast = ast::StaticDef;
90 fn source(self, db: &impl DefDatabase) -> Source<ast::StaticDef> { 90 fn source(self, db: &impl DefDatabase) -> Source<ast::StaticDef> {
91 self.id.source(db) 91 self.id.lookup(db).source(db)
92 } 92 }
93} 93}
94impl HasSource for Trait { 94impl HasSource for Trait {
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index c3c3b05ed..f506bba70 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -104,10 +104,21 @@ impl FromSource for Const {
104impl FromSource for Static { 104impl FromSource for Static {
105 type Ast = ast::StaticDef; 105 type Ast = ast::StaticDef;
106 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 106 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
107 let id = from_source(db, src)?; 107 let module = match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
108 Some(Static { id }) 108 Container::Module(it) => it,
109 Container::Trait(_) | Container::ImplBlock(_) => return None,
110 };
111 module
112 .declarations(db)
113 .into_iter()
114 .filter_map(|it| match it {
115 ModuleDef::Static(it) => Some(it),
116 _ => None,
117 })
118 .find(|it| same_source(&it.source(db), &src))
109 } 119 }
110} 120}
121
111impl FromSource for TypeAlias { 122impl FromSource for TypeAlias {
112 type Ast = ast::TypeAliasDef; 123 type Ast = ast::TypeAliasDef;
113 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 124 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
@@ -271,7 +282,9 @@ where
271 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); 282 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
272 let module = Module::from_definition(db, Source::new(src.file_id, module_src))?; 283 let module = Module::from_definition(db, Source::new(src.file_id, module_src))?;
273 let ctx = LocationCtx::new(db, module.id, src.file_id); 284 let ctx = LocationCtx::new(db, module.id, src.file_id);
274 Some(DEF::from_ast(ctx, &src.value)) 285 let items = db.ast_id_map(src.file_id);
286 let item_id = items.ast_id(&src.value);
287 Some(DEF::from_ast_id(ctx, item_id))
275} 288}
276 289
277enum Container { 290enum Container {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 0a836c913..cfc4bd326 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -11,7 +11,7 @@ use hir_def::{
11 expr::{ExprId, PatId}, 11 expr::{ExprId, PatId},
12 path::known, 12 path::known,
13 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, 13 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
14 DefWithBodyId, LocationCtx, 14 DefWithBodyId,
15}; 15};
16use hir_expand::{ 16use hir_expand::{
17 name::AsName, AstId, HirFileId, MacroCallId, MacroCallLoc, MacroFileKind, Source, 17 name::AsName, AstId, HirFileId, MacroCallId, MacroCallLoc, MacroFileKind, Source,
@@ -28,8 +28,8 @@ use crate::{
28 expr::{BodySourceMap, ExprScopes, ScopeId}, 28 expr::{BodySourceMap, ExprScopes, ScopeId},
29 ty::method_resolution::{self, implements_trait}, 29 ty::method_resolution::{self, implements_trait},
30 Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, 30 Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function,
31 GenericParam, HasBody, Local, MacroDef, Module, Name, Path, ScopeDef, Static, Struct, Trait, 31 GenericParam, HasBody, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty,
32 Ty, TypeAlias, 32 TypeAlias,
33}; 33};
34 34
35fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { 35fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> {
@@ -68,16 +68,12 @@ fn def_with_body_from_child_node(
68 db: &impl HirDatabase, 68 db: &impl HirDatabase,
69 child: Source<&SyntaxNode>, 69 child: Source<&SyntaxNode>,
70) -> Option<DefWithBody> { 70) -> Option<DefWithBody> {
71 let module_source = crate::ModuleSource::from_child_node(db, child);
72 let module = Module::from_definition(db, Source::new(child.file_id, module_source))?;
73 let ctx = LocationCtx::new(db, module.id, child.file_id);
74
75 child.value.ancestors().find_map(|node| { 71 child.value.ancestors().find_map(|node| {
76 match_ast! { 72 match_ast! {
77 match node { 73 match node {
78 ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); }, 74 ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); },
79 ast::ConstDef(def) => { return Const::from_source(db, child.with_value(def)).map(DefWithBody::from); }, 75 ast::ConstDef(def) => { return Const::from_source(db, child.with_value(def)).map(DefWithBody::from); },
80 ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) }, 76 ast::StaticDef(def) => { return Static::from_source(db, child.with_value(def)).map(DefWithBody::from); },
81 _ => { None }, 77 _ => { None },
82 } 78 }
83 } 79 }
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 17a50cf74..3209c66bd 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2550,8 +2550,6 @@ fn test() {
2550 [233; 246) 'GLOBAL_STATIC': u32 2550 [233; 246) 'GLOBAL_STATIC': u32
2551 [256; 257) 'w': u32 2551 [256; 257) 'w': u32
2552 [260; 277) 'GLOBAL...IC_MUT': u32 2552 [260; 277) 'GLOBAL...IC_MUT': u32
2553 [118; 120) '99': u32
2554 [161; 163) '99': u32
2555 "### 2553 "###
2556 ); 2554 );
2557} 2555}
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 b063530c2..f60feb5fa 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -94,25 +94,10 @@ impl<'a, DB> LocationCtx<&'a DB> {
94 } 94 }
95} 95}
96 96
97impl<'a, DB: AstDatabase + InternDatabase> LocationCtx<&'a DB> {
98 pub fn to_def<N, DEF>(self, ast: &N) -> DEF
99 where
100 N: AstNode,
101 DEF: AstItemDef<N>,
102 {
103 DEF::from_ast(self, ast)
104 }
105}
106
107pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone { 97pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
108 fn intern(db: &impl InternDatabase, loc: ItemLoc<N>) -> Self; 98 fn intern(db: &impl InternDatabase, loc: ItemLoc<N>) -> Self;
109 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<N>; 99 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<N>;
110 100
111 fn from_ast(ctx: LocationCtx<&(impl AstDatabase + InternDatabase)>, ast: &N) -> Self {
112 let items = ctx.db.ast_id_map(ctx.file_id);
113 let item_id = items.ast_id(ast);
114 Self::from_ast_id(ctx, item_id)
115 }
116 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 {
117 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) };
118 Self::intern(ctx.db, loc) 103 Self::intern(ctx.db, loc)
@@ -245,12 +230,24 @@ impl Lookup for ConstId {
245#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 230#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
246pub struct StaticId(salsa::InternId); 231pub struct StaticId(salsa::InternId);
247impl_intern_key!(StaticId); 232impl_intern_key!(StaticId);
248impl AstItemDef<ast::StaticDef> for StaticId { 233
249 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StaticDef>) -> Self { 234#[derive(Debug, Clone, PartialEq, Eq, Hash)]
250 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)
251 } 244 }
252 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StaticDef> { 245}
253 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)
254 } 251 }
255} 252}
256 253
@@ -481,6 +478,12 @@ impl HasModule for ConstLoc {
481 } 478 }
482} 479}
483 480
481impl HasModule for StaticLoc {
482 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId {
483 self.container
484 }
485}
486
484pub trait HasSource { 487pub trait HasSource {
485 type Value; 488 type Value;
486 fn source(&self, db: &impl db::DefDatabase) -> Source<Self::Value>; 489 fn source(&self, db: &impl db::DefDatabase) -> Source<Self::Value>;
@@ -513,6 +516,15 @@ impl HasSource for ConstLoc {
513 } 516 }
514} 517}
515 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
516pub trait HasChildSource { 528pub trait HasChildSource {
517 type ChildId; 529 type ChildId;
518 type Value; 530 type Value;
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 1d004b6a6..7a5f90327 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -7,7 +7,7 @@ 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, FxHashSet}; 11use rustc_hash::{FxHashMap, FxHashSet};
12use test_utils::tested_by; 12use test_utils::tested_by;
13 13
@@ -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
@@ -599,8 +599,8 @@ where
599 } 599 }
600 600
601 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) { 601 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) {
602 let path_attr = self.path_attr(attrs); 602 let path_attr = attrs.by_key("path").string_value();
603 let is_macro_use = attrs.has_atom("macro_use"); 603 let is_macro_use = attrs.by_key("macro_use").exists();
604 match module { 604 match module {
605 // inline module, just recurse 605 // inline module, just recurse
606 raw::ModuleData::Definition { name, items, ast_id } => { 606 raw::ModuleData::Definition { name, items, ast_id } => {
@@ -715,7 +715,10 @@ where
715 PerNs::values(def.into()) 715 PerNs::values(def.into())
716 } 716 }
717 raw::DefKind::Static(ast_id) => { 717 raw::DefKind::Static(ast_id) => {
718 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())
719 } 722 }
720 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()),
721 raw::DefKind::TypeAlias(ast_id) => { 724 raw::DefKind::TypeAlias(ast_id) => {
@@ -793,11 +796,11 @@ where
793 } 796 }
794 797
795 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { 798 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
796 attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false)) 799 // FIXME: handle cfg_attr :-)
797 } 800 attrs
798 801 .by_key("cfg")
799 fn path_attr<'a>(&self, attrs: &'a Attrs) -> Option<&'a SmolStr> { 802 .tt_values()
800 attrs.iter().find_map(|attr| attr.as_path()) 803 .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false))
801 } 804 }
802} 805}
803 806
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
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index 896ad1517..bac3f7582 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -288,7 +288,7 @@ impl Completions {
288} 288}
289 289
290fn is_deprecated(node: impl HasAttrs, db: &impl HirDatabase) -> bool { 290fn is_deprecated(node: impl HasAttrs, db: &impl HirDatabase) -> bool {
291 node.attrs(db).has_atom("deprecated") 291 node.attrs(db).by_key("deprecated").exists()
292} 292}
293 293
294fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool { 294fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool {