aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/body.rs22
-rw-r--r--crates/ra_hir_def/src/body/lower.rs3
-rw-r--r--crates/ra_hir_def/src/data.rs119
-rw-r--r--crates/ra_hir_def/src/expr.rs1
-rw-r--r--crates/ra_hir_def/src/lib.rs1
-rw-r--r--crates/ra_hir_def/src/path.rs2
6 files changed, 98 insertions, 50 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index d9ce6bcff..445d215b7 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -24,7 +24,7 @@ use crate::{
24 DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId, 24 DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId,
25}; 25};
26 26
27struct Expander { 27pub(crate) struct Expander {
28 crate_def_map: Arc<CrateDefMap>, 28 crate_def_map: Arc<CrateDefMap>,
29 current_file_id: HirFileId, 29 current_file_id: HirFileId,
30 hygiene: Hygiene, 30 hygiene: Hygiene,
@@ -33,18 +33,22 @@ struct Expander {
33} 33}
34 34
35impl Expander { 35impl Expander {
36 fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { 36 pub(crate) fn new(
37 db: &impl DefDatabase,
38 current_file_id: HirFileId,
39 module: ModuleId,
40 ) -> Expander {
37 let crate_def_map = db.crate_def_map(module.krate); 41 let crate_def_map = db.crate_def_map(module.krate);
38 let hygiene = Hygiene::new(db, current_file_id); 42 let hygiene = Hygiene::new(db, current_file_id);
39 let ast_id_map = db.ast_id_map(current_file_id); 43 let ast_id_map = db.ast_id_map(current_file_id);
40 Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module } 44 Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module }
41 } 45 }
42 46
43 fn enter_expand( 47 pub(crate) fn enter_expand<T: ast::AstNode, DB: DefDatabase>(
44 &mut self, 48 &mut self,
45 db: &impl DefDatabase, 49 db: &DB,
46 macro_call: ast::MacroCall, 50 macro_call: ast::MacroCall,
47 ) -> Option<(Mark, ast::Expr)> { 51 ) -> Option<(Mark, T)> {
48 let ast_id = AstId::new( 52 let ast_id = AstId::new(
49 self.current_file_id, 53 self.current_file_id,
50 db.ast_id_map(self.current_file_id).ast_id(&macro_call), 54 db.ast_id_map(self.current_file_id).ast_id(&macro_call),
@@ -55,7 +59,7 @@ impl Expander {
55 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); 59 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id));
56 let file_id = call_id.as_file(); 60 let file_id = call_id.as_file();
57 if let Some(node) = db.parse_or_expand(file_id) { 61 if let Some(node) = db.parse_or_expand(file_id) {
58 if let Some(expr) = ast::Expr::cast(node) { 62 if let Some(expr) = T::cast(node) {
59 log::debug!("macro expansion {:#?}", expr.syntax()); 63 log::debug!("macro expansion {:#?}", expr.syntax());
60 64
61 let mark = Mark { 65 let mark = Mark {
@@ -78,14 +82,14 @@ impl Expander {
78 None 82 None
79 } 83 }
80 84
81 fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) { 85 pub(crate) fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) {
82 self.hygiene = Hygiene::new(db, mark.file_id); 86 self.hygiene = Hygiene::new(db, mark.file_id);
83 self.current_file_id = mark.file_id; 87 self.current_file_id = mark.file_id;
84 self.ast_id_map = mem::take(&mut mark.ast_id_map); 88 self.ast_id_map = mem::take(&mut mark.ast_id_map);
85 mark.bomb.defuse(); 89 mark.bomb.defuse();
86 } 90 }
87 91
88 fn to_source<T>(&self, value: T) -> InFile<T> { 92 pub(crate) fn to_source<T>(&self, value: T) -> InFile<T> {
89 InFile { file_id: self.current_file_id, value } 93 InFile { file_id: self.current_file_id, value }
90 } 94 }
91 95
@@ -110,7 +114,7 @@ impl Expander {
110 } 114 }
111} 115}
112 116
113struct Mark { 117pub(crate) struct Mark {
114 file_id: HirFileId, 118 file_id: HirFileId,
115 ast_id_map: Arc<AstIdMap>, 119 ast_id_map: Arc<AstIdMap>,
116 bomb: DropBomb, 120 bomb: DropBomb,
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 853e17bae..be5d17d85 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -372,8 +372,9 @@ where
372 arg_types.push(type_ref); 372 arg_types.push(type_ref);
373 } 373 }
374 } 374 }
375 let ret_type = e.ret_type().and_then(|r| r.type_ref()).map(TypeRef::from_ast);
375 let body = self.collect_expr_opt(e.body()); 376 let body = self.collect_expr_opt(e.body());
376 self.alloc_expr(Expr::Lambda { args, arg_types, body }, syntax_ptr) 377 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
377 } 378 }
378 ast::Expr::BinExpr(e) => { 379 ast::Expr::BinExpr(e) => {
379 let lhs = self.collect_expr_opt(e.lhs()); 380 let lhs = self.collect_expr_opt(e.lhs());
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 14e86936b..b0a3f1784 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -4,16 +4,16 @@ use std::sync::Arc;
4 4
5use hir_expand::{ 5use hir_expand::{
6 name::{name, AsName, Name}, 6 name::{name, AsName, Name},
7 AstId, 7 AstId, InFile,
8}; 8};
9use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 9use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner};
10 10
11use crate::{ 11use crate::{
12 db::DefDatabase, 12 db::DefDatabase,
13 src::HasSource, 13 src::HasSource,
14 type_ref::{Mutability, TypeRef}, 14 type_ref::{Mutability, TypeRef},
15 AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, ImplId, Intern, 15 AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule,
16 Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc, 16 ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
17}; 17};
18 18
19#[derive(Debug, Clone, PartialEq, Eq)] 19#[derive(Debug, Clone, PartialEq, Eq)]
@@ -167,46 +167,24 @@ pub struct ImplData {
167 167
168impl ImplData { 168impl ImplData {
169 pub(crate) fn impl_data_query(db: &impl DefDatabase, id: ImplId) -> Arc<ImplData> { 169 pub(crate) fn impl_data_query(db: &impl DefDatabase, id: ImplId) -> Arc<ImplData> {
170 let src = id.lookup(db).source(db); 170 let impl_loc = id.lookup(db);
171 let items = db.ast_id_map(src.file_id); 171 let src = impl_loc.source(db);
172 172
173 let target_trait = src.value.target_trait().map(TypeRef::from_ast); 173 let target_trait = src.value.target_trait().map(TypeRef::from_ast);
174 let target_type = TypeRef::from_ast_opt(src.value.target_type()); 174 let target_type = TypeRef::from_ast_opt(src.value.target_type());
175 let is_negative = src.value.is_negative(); 175 let is_negative = src.value.is_negative();
176 let module_id = impl_loc.container.module(db);
176 177
177 let items = if let Some(item_list) = src.value.item_list() { 178 let mut items = Vec::new();
178 item_list 179 if let Some(item_list) = src.value.item_list() {
179 .impl_items() 180 items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id));
180 .map(|item_node| match item_node { 181 items.extend(collect_impl_items_in_macros(
181 ast::ImplItem::FnDef(it) => { 182 db,
182 let def = FunctionLoc { 183 module_id,
183 container: AssocContainerId::ImplId(id), 184 &src.with_value(item_list),
184 ast_id: AstId::new(src.file_id, items.ast_id(&it)), 185 id,
185 } 186 ));
186 .intern(db); 187 }
187 def.into()
188 }
189 ast::ImplItem::ConstDef(it) => {
190 let def = ConstLoc {
191 container: AssocContainerId::ImplId(id),
192 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
193 }
194 .intern(db);
195 def.into()
196 }
197 ast::ImplItem::TypeAliasDef(it) => {
198 let def = TypeAliasLoc {
199 container: AssocContainerId::ImplId(id),
200 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
201 }
202 .intern(db);
203 def.into()
204 }
205 })
206 .collect()
207 } else {
208 Vec::new()
209 };
210 188
211 let res = ImplData { target_trait, target_type, items, is_negative }; 189 let res = ImplData { target_trait, target_type, items, is_negative };
212 Arc::new(res) 190 Arc::new(res)
@@ -237,3 +215,66 @@ impl ConstData {
237 ConstData { name, type_ref } 215 ConstData { name, type_ref }
238 } 216 }
239} 217}
218
219fn collect_impl_items_in_macros(
220 db: &impl DefDatabase,
221 module_id: ModuleId,
222 impl_block: &InFile<ast::ItemList>,
223 id: ImplId,
224) -> Vec<AssocItemId> {
225 let mut expander = Expander::new(db, impl_block.file_id, module_id);
226 let mut res = Vec::new();
227
228 for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) {
229 if let Some((mark, items)) = expander.enter_expand(db, m) {
230 let items: InFile<ast::MacroItems> = expander.to_source(items);
231 expander.exit(db, mark);
232 res.extend(collect_impl_items(
233 db,
234 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())),
235 items.file_id,
236 id,
237 ));
238 }
239 }
240
241 res
242}
243
244fn collect_impl_items(
245 db: &impl DefDatabase,
246 impl_items: impl Iterator<Item = ImplItem>,
247 file_id: crate::HirFileId,
248 id: ImplId,
249) -> Vec<AssocItemId> {
250 let items = db.ast_id_map(file_id);
251
252 impl_items
253 .map(|item_node| match item_node {
254 ast::ImplItem::FnDef(it) => {
255 let def = FunctionLoc {
256 container: AssocContainerId::ImplId(id),
257 ast_id: AstId::new(file_id, items.ast_id(&it)),
258 }
259 .intern(db);
260 def.into()
261 }
262 ast::ImplItem::ConstDef(it) => {
263 let def = ConstLoc {
264 container: AssocContainerId::ImplId(id),
265 ast_id: AstId::new(file_id, items.ast_id(&it)),
266 }
267 .intern(db);
268 def.into()
269 }
270 ast::ImplItem::TypeAliasDef(it) => {
271 let def = TypeAliasLoc {
272 container: AssocContainerId::ImplId(id),
273 ast_id: AstId::new(file_id, items.ast_id(&it)),
274 }
275 .intern(db);
276 def.into()
277 }
278 })
279 .collect()
280}
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index 6fad80a8d..a75ef9970 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -143,6 +143,7 @@ pub enum Expr {
143 Lambda { 143 Lambda {
144 args: Vec<PatId>, 144 args: Vec<PatId>,
145 arg_types: Vec<Option<TypeRef>>, 145 arg_types: Vec<Option<TypeRef>>,
146 ret_type: Option<TypeRef>,
146 body: ExprId, 147 body: ExprId,
147 }, 148 },
148 Tuple { 149 Tuple {
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index bf8d6d1d4..acd4f4af1 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -48,6 +48,7 @@ use ra_arena::{impl_arena_id, RawId};
48use ra_db::{impl_intern_key, salsa, CrateId}; 48use ra_db::{impl_intern_key, salsa, CrateId};
49use ra_syntax::{ast, AstNode}; 49use ra_syntax::{ast, AstNode};
50 50
51use crate::body::Expander;
51use crate::builtin_type::BuiltinType; 52use crate::builtin_type::BuiltinType;
52 53
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 54#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 00325cd99..8e1294201 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -135,7 +135,7 @@ impl Path {
135 } 135 }
136 136
137 pub fn type_anchor(&self) -> Option<&TypeRef> { 137 pub fn type_anchor(&self) -> Option<&TypeRef> {
138 self.type_anchor.as_ref().map(|it| &**it) 138 self.type_anchor.as_deref()
139 } 139 }
140 140
141 pub fn segments(&self) -> PathSegments<'_> { 141 pub fn segments(&self) -> PathSegments<'_> {