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/adt.rs15
-rw-r--r--crates/ra_hir_def/src/body.rs11
-rw-r--r--crates/ra_hir_def/src/body/lower.rs6
-rw-r--r--crates/ra_hir_def/src/data.rs149
4 files changed, 77 insertions, 104 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 8eef51828..2bc34d449 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -117,7 +117,14 @@ fn lower_enum(
117 ast: &InFile<ast::EnumDef>, 117 ast: &InFile<ast::EnumDef>,
118 module_id: ModuleId, 118 module_id: ModuleId,
119) { 119) {
120 for var in ast.value.variant_list().into_iter().flat_map(|it| it.variants()) { 120 let expander = CfgExpander::new(db, ast.file_id, module_id.krate);
121 let variants = ast
122 .value
123 .variant_list()
124 .into_iter()
125 .flat_map(|it| it.variants())
126 .filter(|var| expander.is_cfg_enabled(var));
127 for var in variants {
121 trace.alloc( 128 trace.alloc(
122 || var.clone(), 129 || var.clone(),
123 || EnumVariantData { 130 || EnumVariantData {
@@ -209,8 +216,7 @@ fn lower_struct(
209 match &ast.value { 216 match &ast.value {
210 ast::StructKind::Tuple(fl) => { 217 ast::StructKind::Tuple(fl) => {
211 for (i, fd) in fl.fields().enumerate() { 218 for (i, fd) in fl.fields().enumerate() {
212 let attrs = expander.parse_attrs(&fd); 219 if !expander.is_cfg_enabled(&fd) {
213 if !expander.is_cfg_enabled(&attrs) {
214 continue; 220 continue;
215 } 221 }
216 222
@@ -227,8 +233,7 @@ fn lower_struct(
227 } 233 }
228 ast::StructKind::Record(fl) => { 234 ast::StructKind::Record(fl) => {
229 for fd in fl.fields() { 235 for fd in fl.fields() {
230 let attrs = expander.parse_attrs(&fd); 236 if !expander.is_cfg_enabled(&fd) {
231 if !expander.is_cfg_enabled(&attrs) {
232 continue; 237 continue;
233 } 238 }
234 239
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 4edaad960..f5a7305dc 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -60,7 +60,8 @@ impl CfgExpander {
60 Attrs::new(owner, &self.hygiene) 60 Attrs::new(owner, &self.hygiene)
61 } 61 }
62 62
63 pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { 63 pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool {
64 let attrs = self.parse_attrs(owner);
64 attrs.is_cfg_enabled(&self.cfg_options) 65 attrs.is_cfg_enabled(&self.cfg_options)
65 } 66 }
66} 67}
@@ -141,12 +142,8 @@ impl Expander {
141 InFile { file_id: self.current_file_id, value } 142 InFile { file_id: self.current_file_id, value }
142 } 143 }
143 144
144 pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { 145 pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool {
145 self.cfg_expander.parse_attrs(owner) 146 self.cfg_expander.is_cfg_enabled(owner)
146 }
147
148 pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
149 self.cfg_expander.is_cfg_enabled(attrs)
150 } 147 }
151 148
152 fn parse_path(&mut self, path: ast::Path) -> Option<Path> { 149 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 4671b72e9..443b057ab 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -162,8 +162,7 @@ impl ExprCollector<'_> {
162 162
163 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { 163 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
164 let syntax_ptr = AstPtr::new(&expr); 164 let syntax_ptr = AstPtr::new(&expr);
165 let attrs = self.expander.parse_attrs(&expr); 165 if !self.expander.is_cfg_enabled(&expr) {
166 if !self.expander.is_cfg_enabled(&attrs) {
167 return self.missing_expr(); 166 return self.missing_expr();
168 } 167 }
169 match expr { 168 match expr {
@@ -329,8 +328,7 @@ impl ExprCollector<'_> {
329 .fields() 328 .fields()
330 .inspect(|field| field_ptrs.push(AstPtr::new(field))) 329 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
331 .filter_map(|field| { 330 .filter_map(|field| {
332 let attrs = self.expander.parse_attrs(&field); 331 if !self.expander.is_cfg_enabled(&field) {
333 if !self.expander.is_cfg_enabled(&attrs) {
334 return None; 332 return None;
335 } 333 }
336 let name = field.field_name()?.as_name(); 334 let name = field.field_name()?.as_name();
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 7a2067e49..2dbae04d3 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -150,51 +150,31 @@ pub struct TraitData {
150 150
151impl TraitData { 151impl TraitData {
152 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { 152 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
153 let src = tr.lookup(db).source(db); 153 let tr_loc = tr.lookup(db);
154 let src = tr_loc.source(db);
154 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 155 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
155 let auto = src.value.auto_token().is_some(); 156 let auto = src.value.auto_token().is_some();
156 let ast_id_map = db.ast_id_map(src.file_id); 157 let module_id = tr_loc.container.module(db);
157 158
158 let container = AssocContainerId::TraitId(tr); 159 let container = AssocContainerId::TraitId(tr);
159 let items = if let Some(item_list) = src.value.item_list() { 160 let mut items = Vec::new();
160 item_list 161
161 .impl_items() 162 if let Some(item_list) = src.value.item_list() {
162 .map(|item_node| match item_node { 163 let mut expander = Expander::new(db, tr_loc.ast_id.file_id, module_id);
163 ast::ImplItem::FnDef(it) => { 164 items.extend(collect_items(
164 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 165 db,
165 let def = FunctionLoc { 166 &mut expander,
166 container, 167 item_list.impl_items(),
167 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), 168 src.file_id,
168 } 169 container,
169 .intern(db) 170 ));
170 .into(); 171 items.extend(collect_items_in_macros(
171 (name, def) 172 db,
172 } 173 &mut expander,
173 ast::ImplItem::ConstDef(it) => { 174 &src.with_value(item_list),
174 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 175 container,
175 let def = ConstLoc { 176 ));
176 container, 177 }
177 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
178 }
179 .intern(db)
180 .into();
181 (name, def)
182 }
183 ast::ImplItem::TypeAliasDef(it) => {
184 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
185 let def = TypeAliasLoc {
186 container,
187 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
188 }
189 .intern(db)
190 .into();
191 (name, def)
192 }
193 })
194 .collect()
195 } else {
196 Vec::new()
197 };
198 Arc::new(TraitData { name, items, auto }) 178 Arc::new(TraitData { name, items, auto })
199 } 179 }
200 180
@@ -232,24 +212,22 @@ impl ImplData {
232 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type()); 212 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type());
233 let is_negative = src.value.excl_token().is_some(); 213 let is_negative = src.value.excl_token().is_some();
234 let module_id = impl_loc.container.module(db); 214 let module_id = impl_loc.container.module(db);
215 let container = AssocContainerId::ImplId(id);
235 216
236 let mut items = Vec::new(); 217 let mut items: Vec<AssocItemId> = Vec::new();
237 218
238 if let Some(item_list) = src.value.item_list() { 219 if let Some(item_list) = src.value.item_list() {
239 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); 220 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
240 items.extend(collect_impl_items( 221 items.extend(
241 db, 222 collect_items(db, &mut expander, item_list.impl_items(), src.file_id, container)
242 &mut expander, 223 .into_iter()
243 item_list.impl_items(), 224 .map(|(_, item)| item),
244 src.file_id, 225 );
245 id, 226 items.extend(
246 )); 227 collect_items_in_macros(db, &mut expander, &src.with_value(item_list), container)
247 items.extend(collect_impl_items_in_macros( 228 .into_iter()
248 db, 229 .map(|(_, item)| item),
249 &mut expander, 230 );
250 &src.with_value(item_list),
251 id,
252 ));
253 } 231 }
254 232
255 let res = ImplData { target_trait, target_type, items, is_negative }; 233 let res = ImplData { target_trait, target_type, items, is_negative };
@@ -292,49 +270,50 @@ impl ConstData {
292 } 270 }
293} 271}
294 272
295fn collect_impl_items_in_macros( 273fn collect_items_in_macros(
296 db: &dyn DefDatabase, 274 db: &dyn DefDatabase,
297 expander: &mut Expander, 275 expander: &mut Expander,
298 impl_def: &InFile<ast::ItemList>, 276 impl_def: &InFile<ast::ItemList>,
299 id: ImplId, 277 container: AssocContainerId,
300) -> Vec<AssocItemId> { 278) -> Vec<(Name, AssocItemId)> {
301 let mut res = Vec::new(); 279 let mut res = Vec::new();
302 280
303 // We set a limit to protect against infinite recursion 281 // We set a limit to protect against infinite recursion
304 let limit = 100; 282 let limit = 100;
305 283
306 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { 284 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) {
307 res.extend(collect_impl_items_in_macro(db, expander, m, id, limit)) 285 res.extend(collect_items_in_macro(db, expander, m, container, limit))
308 } 286 }
309 287
310 res 288 res
311} 289}
312 290
313fn collect_impl_items_in_macro( 291fn collect_items_in_macro(
314 db: &dyn DefDatabase, 292 db: &dyn DefDatabase,
315 expander: &mut Expander, 293 expander: &mut Expander,
316 m: ast::MacroCall, 294 m: ast::MacroCall,
317 id: ImplId, 295 container: AssocContainerId,
318 limit: usize, 296 limit: usize,
319) -> Vec<AssocItemId> { 297) -> Vec<(Name, AssocItemId)> {
320 if limit == 0 { 298 if limit == 0 {
321 return Vec::new(); 299 return Vec::new();
322 } 300 }
323 301
324 if let Some((mark, items)) = expander.enter_expand(db, None, m) { 302 if let Some((mark, items)) = expander.enter_expand(db, None, m) {
325 let items: InFile<ast::MacroItems> = expander.to_source(items); 303 let items: InFile<ast::MacroItems> = expander.to_source(items);
326 let mut res = collect_impl_items( 304 let mut res = collect_items(
327 db, 305 db,
328 expander, 306 expander,
329 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), 307 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())),
330 items.file_id, 308 items.file_id,
331 id, 309 container,
332 ); 310 );
311
333 // Recursive collect macros 312 // Recursive collect macros
334 // Note that ast::ModuleItem do not include ast::MacroCall 313 // Note that ast::ModuleItem do not include ast::MacroCall
335 // We cannot use ModuleItemOwner::items here 314 // We cannot use ModuleItemOwner::items here
336 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { 315 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) {
337 res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1)) 316 res.extend(collect_items_in_macro(db, expander, it, container, limit - 1))
338 } 317 }
339 expander.exit(db, mark); 318 expander.exit(db, mark);
340 res 319 res
@@ -343,44 +322,38 @@ fn collect_impl_items_in_macro(
343 } 322 }
344} 323}
345 324
346fn collect_impl_items( 325fn collect_items(
347 db: &dyn DefDatabase, 326 db: &dyn DefDatabase,
348 expander: &mut Expander, 327 expander: &mut Expander,
349 impl_items: impl Iterator<Item = ImplItem>, 328 impl_items: impl Iterator<Item = ImplItem>,
350 file_id: crate::HirFileId, 329 file_id: crate::HirFileId,
351 id: ImplId, 330 container: AssocContainerId,
352) -> Vec<AssocItemId> { 331) -> Vec<(Name, AssocItemId)> {
353 let items = db.ast_id_map(file_id); 332 let items = db.ast_id_map(file_id);
354 333
355 impl_items 334 impl_items
356 .filter_map(|item_node| match item_node { 335 .filter_map(|item_node| match item_node {
357 ast::ImplItem::FnDef(it) => { 336 ast::ImplItem::FnDef(it) => {
358 let attrs = expander.parse_attrs(&it); 337 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
359 if !expander.is_cfg_enabled(&attrs) { 338 if !expander.is_cfg_enabled(&it) {
360 return None; 339 return None;
361 } 340 }
362 let def = FunctionLoc { 341 let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
363 container: AssocContainerId::ImplId(id), 342 .intern(db);
364 ast_id: AstId::new(file_id, items.ast_id(&it)), 343 Some((name, def.into()))
365 }
366 .intern(db);
367 Some(def.into())
368 } 344 }
369 ast::ImplItem::ConstDef(it) => { 345 ast::ImplItem::ConstDef(it) => {
370 let def = ConstLoc { 346 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
371 container: AssocContainerId::ImplId(id), 347 let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
372 ast_id: AstId::new(file_id, items.ast_id(&it)), 348 .intern(db);
373 } 349 Some((name, def.into()))
374 .intern(db);
375 Some(def.into())
376 } 350 }
377 ast::ImplItem::TypeAliasDef(it) => { 351 ast::ImplItem::TypeAliasDef(it) => {
378 let def = TypeAliasLoc { 352 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
379 container: AssocContainerId::ImplId(id), 353 let def =
380 ast_id: AstId::new(file_id, items.ast_id(&it)), 354 TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
381 } 355 .intern(db);
382 .intern(db); 356 Some((name, def.into()))
383 Some(def.into())
384 } 357 }
385 }) 358 })
386 .collect() 359 .collect()