diff options
Diffstat (limited to 'crates/hir')
-rw-r--r-- | crates/hir/src/semantics.rs | 66 | ||||
-rw-r--r-- | crates/hir/src/semantics/source_to_def.rs | 15 |
2 files changed, 61 insertions, 20 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index c7f2c02e4..0d55e4a3e 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -362,25 +362,57 @@ impl<'db> SemanticsImpl<'db> { | |||
362 | 362 | ||
363 | let token = successors(Some(InFile::new(sa.file_id, token)), |token| { | 363 | let token = successors(Some(InFile::new(sa.file_id, token)), |token| { |
364 | self.db.unwind_if_cancelled(); | 364 | self.db.unwind_if_cancelled(); |
365 | let macro_call = token.value.ancestors().find_map(ast::MacroCall::cast)?; | 365 | |
366 | let tt = macro_call.token_tree()?; | 366 | for node in token.value.ancestors() { |
367 | if !tt.syntax().text_range().contains_range(token.value.text_range()) { | 367 | match_ast! { |
368 | return None; | 368 | match node { |
369 | } | 369 | ast::MacroCall(macro_call) => { |
370 | let file_id = sa.expand(self.db, token.with_value(¯o_call))?; | 370 | let tt = macro_call.token_tree()?; |
371 | let token = self | 371 | if !tt.syntax().text_range().contains_range(token.value.text_range()) { |
372 | .expansion_info_cache | 372 | return None; |
373 | .borrow_mut() | 373 | } |
374 | .entry(file_id) | 374 | let file_id = sa.expand(self.db, token.with_value(¯o_call))?; |
375 | .or_insert_with(|| file_id.expansion_info(self.db.upcast())) | 375 | let token = self |
376 | .as_ref()? | 376 | .expansion_info_cache |
377 | .map_token_down(token.as_ref())?; | 377 | .borrow_mut() |
378 | 378 | .entry(file_id) | |
379 | if let Some(parent) = token.value.parent() { | 379 | .or_insert_with(|| file_id.expansion_info(self.db.upcast())) |
380 | self.cache(find_root(&parent), token.file_id); | 380 | .as_ref()? |
381 | .map_token_down(token.as_ref())?; | ||
382 | |||
383 | if let Some(parent) = token.value.parent() { | ||
384 | self.cache(find_root(&parent), token.file_id); | ||
385 | } | ||
386 | |||
387 | return Some(token); | ||
388 | }, | ||
389 | ast::Item(item) => { | ||
390 | match self.with_ctx(|ctx| ctx.item_to_macro_call(token.with_value(item))) { | ||
391 | Some(call_id) => { | ||
392 | let file_id = call_id.as_file(); | ||
393 | let token = self | ||
394 | .expansion_info_cache | ||
395 | .borrow_mut() | ||
396 | .entry(file_id) | ||
397 | .or_insert_with(|| file_id.expansion_info(self.db.upcast())) | ||
398 | .as_ref()? | ||
399 | .map_token_down(token.as_ref())?; | ||
400 | |||
401 | if let Some(parent) = token.value.parent() { | ||
402 | self.cache(find_root(&parent), token.file_id); | ||
403 | } | ||
404 | |||
405 | return Some(token); | ||
406 | } | ||
407 | None => {} | ||
408 | } | ||
409 | }, | ||
410 | _ => {} | ||
411 | } | ||
412 | } | ||
381 | } | 413 | } |
382 | 414 | ||
383 | Some(token) | 415 | None |
384 | }) | 416 | }) |
385 | .last() | 417 | .last() |
386 | .unwrap(); | 418 | .unwrap(); |
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index 9a5a2255f..22e196196 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs | |||
@@ -10,7 +10,7 @@ use hir_def::{ | |||
10 | ImplId, LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, | 10 | ImplId, LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, |
11 | UnionId, VariantId, | 11 | UnionId, VariantId, |
12 | }; | 12 | }; |
13 | use hir_expand::{name::AsName, AstId, MacroDefKind}; | 13 | use hir_expand::{name::AsName, AstId, MacroCallId, MacroDefKind}; |
14 | use rustc_hash::FxHashMap; | 14 | use rustc_hash::FxHashMap; |
15 | use smallvec::SmallVec; | 15 | use smallvec::SmallVec; |
16 | use stdx::impl_from; | 16 | use stdx::impl_from; |
@@ -145,16 +145,25 @@ impl SourceToDefCtx<'_, '_> { | |||
145 | Some((container, label_id)) | 145 | Some((container, label_id)) |
146 | } | 146 | } |
147 | 147 | ||
148 | pub(super) fn item_to_macro_call(&mut self, src: InFile<ast::Item>) -> Option<MacroCallId> { | ||
149 | let map = self.dyn_map(src.as_ref())?; | ||
150 | map[keys::ATTR_MACRO].get(&src).copied() | ||
151 | } | ||
152 | |||
148 | fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>( | 153 | fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>( |
149 | &mut self, | 154 | &mut self, |
150 | src: InFile<Ast>, | 155 | src: InFile<Ast>, |
151 | key: Key<Ast, ID>, | 156 | key: Key<Ast, ID>, |
152 | ) -> Option<ID> { | 157 | ) -> Option<ID> { |
153 | let container = self.find_container(src.as_ref().map(|it| it.syntax()))?; | 158 | self.dyn_map(src.as_ref())?[key].get(&src).copied() |
159 | } | ||
160 | |||
161 | fn dyn_map<Ast: AstNode + 'static>(&mut self, src: InFile<&Ast>) -> Option<&DynMap> { | ||
162 | let container = self.find_container(src.map(|it| it.syntax()))?; | ||
154 | let db = self.db; | 163 | let db = self.db; |
155 | let dyn_map = | 164 | let dyn_map = |
156 | &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db)); | 165 | &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db)); |
157 | dyn_map[key].get(&src).copied() | 166 | Some(dyn_map) |
158 | } | 167 | } |
159 | 168 | ||
160 | pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> { | 169 | pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> { |