mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-30 19:49:36 +00:00 
			
		
		
		
	Fix IDE resolution of item macros
It wasn't inside the source, because there was no source map.
This commit is contained in:
		
							parent
							
								
									1511c5b7fd
								
							
						
					
					
						commit
						3e0ab7219a
					
				
					 6 changed files with 74 additions and 29 deletions
				
			
		|  | @ -422,6 +422,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { | ||||||
|             let makro = &item_tree[loc.id.value]; |             let makro = &item_tree[loc.id.value]; | ||||||
|             MacroDefId { |             MacroDefId { | ||||||
|                 krate: loc.container.krate, |                 krate: loc.container.krate, | ||||||
|  |                 block: loc.container.block.map(|block| salsa::plumbing::AsId::as_id(&block)), | ||||||
|                 kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), |                 kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), | ||||||
|                 local_inner: false, |                 local_inner: false, | ||||||
|                 allow_internal_unsafe: loc.allow_internal_unsafe, |                 allow_internal_unsafe: loc.allow_internal_unsafe, | ||||||
|  | @ -435,6 +436,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { | ||||||
|             let makro = &item_tree[loc.id.value]; |             let makro = &item_tree[loc.id.value]; | ||||||
|             MacroDefId { |             MacroDefId { | ||||||
|                 krate: loc.container.krate, |                 krate: loc.container.krate, | ||||||
|  |                 block: loc.container.block.map(|block| salsa::plumbing::AsId::as_id(&block)), | ||||||
|                 kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), |                 kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), | ||||||
|                 local_inner: loc.flags.contains(MacroRulesLocFlags::LOCAL_INNER), |                 local_inner: loc.flags.contains(MacroRulesLocFlags::LOCAL_INNER), | ||||||
|                 allow_internal_unsafe: loc |                 allow_internal_unsafe: loc | ||||||
|  | @ -450,6 +452,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { | ||||||
|             let makro = &item_tree[loc.id.value]; |             let makro = &item_tree[loc.id.value]; | ||||||
|             MacroDefId { |             MacroDefId { | ||||||
|                 krate: loc.container.krate, |                 krate: loc.container.krate, | ||||||
|  |                 block: None, | ||||||
|                 kind: MacroDefKind::ProcMacro( |                 kind: MacroDefKind::ProcMacro( | ||||||
|                     InFile::new(loc.id.file_id(), makro.ast_id), |                     InFile::new(loc.id.file_id(), makro.ast_id), | ||||||
|                     loc.expander, |                     loc.expander, | ||||||
|  |  | ||||||
|  | @ -696,6 +696,15 @@ impl<'db> Resolver<'db> { | ||||||
|         &def_map[local_id].scope |         &def_map[local_id].scope | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pub fn item_scopes(&self) -> impl Iterator<Item = &ItemScope> { | ||||||
|  |         self.scopes() | ||||||
|  |             .filter_map(move |scope| match scope { | ||||||
|  |                 Scope::BlockScope(m) => Some(&m.def_map[m.module_id].scope), | ||||||
|  |                 _ => None, | ||||||
|  |             }) | ||||||
|  |             .chain(std::iter::once(&self.module_scope.def_map[self.module_scope.module_id].scope)) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     pub fn krate(&self) -> Crate { |     pub fn krate(&self) -> Crate { | ||||||
|         self.module_scope.def_map.krate() |         self.module_scope.def_map.krate() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -258,6 +258,8 @@ pub struct MacroCallLoc { | ||||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||||
| pub struct MacroDefId { | pub struct MacroDefId { | ||||||
|     pub krate: Crate, |     pub krate: Crate, | ||||||
|  |     // FIXME: In `hir-expand` we can't refer to `BlockId`.
 | ||||||
|  |     pub block: Option<salsa::Id>, | ||||||
|     pub edition: Edition, |     pub edition: Edition, | ||||||
|     pub kind: MacroDefKind, |     pub kind: MacroDefKind, | ||||||
|     pub local_inner: bool, |     pub local_inner: bool, | ||||||
|  |  | ||||||
|  | @ -411,7 +411,7 @@ impl<'db> SemanticsImpl<'db> { | ||||||
|         let sa = self.analyze_no_infer(macro_call.syntax())?; |         let sa = self.analyze_no_infer(macro_call.syntax())?; | ||||||
| 
 | 
 | ||||||
|         let macro_call = InFile::new(sa.file_id, macro_call); |         let macro_call = InFile::new(sa.file_id, macro_call); | ||||||
|         let file_id = sa.expand(self.db, macro_call)?; |         let file_id = sa.expansion(self.db, macro_call)?; | ||||||
| 
 | 
 | ||||||
|         let node = self.parse_or_expand(file_id.into()); |         let node = self.parse_or_expand(file_id.into()); | ||||||
|         Some(node) |         Some(node) | ||||||
|  | @ -437,7 +437,7 @@ impl<'db> SemanticsImpl<'db> { | ||||||
|         let sa = self.analyze_no_infer(macro_call.syntax())?; |         let sa = self.analyze_no_infer(macro_call.syntax())?; | ||||||
| 
 | 
 | ||||||
|         let macro_call = InFile::new(sa.file_id, macro_call); |         let macro_call = InFile::new(sa.file_id, macro_call); | ||||||
|         let file_id = sa.expand(self.db, macro_call)?; |         let file_id = sa.expansion(self.db, macro_call)?; | ||||||
|         let macro_call = self.db.lookup_intern_macro_call(file_id); |         let macro_call = self.db.lookup_intern_macro_call(file_id); | ||||||
| 
 | 
 | ||||||
|         let skip = matches!( |         let skip = matches!( | ||||||
|  | @ -576,7 +576,7 @@ impl<'db> SemanticsImpl<'db> { | ||||||
|     ) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> { |     ) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> { | ||||||
|         let analyzer = self.analyze_no_infer(actual_macro_call.syntax())?; |         let analyzer = self.analyze_no_infer(actual_macro_call.syntax())?; | ||||||
|         let macro_call = InFile::new(analyzer.file_id, actual_macro_call); |         let macro_call = InFile::new(analyzer.file_id, actual_macro_call); | ||||||
|         let macro_file = analyzer.expansion(macro_call)?; |         let macro_file = analyzer.expansion(self.db, macro_call)?; | ||||||
|         hir_expand::db::expand_speculative( |         hir_expand::db::expand_speculative( | ||||||
|             self.db, |             self.db, | ||||||
|             macro_file, |             macro_file, | ||||||
|  | @ -1120,7 +1120,7 @@ impl<'db> SemanticsImpl<'db> { | ||||||
|                                                 false, |                                                 false, | ||||||
|                                             ) |                                             ) | ||||||
|                                         })? |                                         })? | ||||||
|                                         .expand(self.db, mcall.as_ref())?; |                                         .expansion(self.db, mcall.as_ref())?; | ||||||
|                                     m_cache.insert(mcall, it); |                                     m_cache.insert(mcall, it); | ||||||
|                                     it |                                     it | ||||||
|                                 } |                                 } | ||||||
|  | @ -1579,7 +1579,7 @@ impl<'db> SemanticsImpl<'db> { | ||||||
|         let sa = self.analyze(macro_call.syntax())?; |         let sa = self.analyze(macro_call.syntax())?; | ||||||
|         self.db |         self.db | ||||||
|             .parse_macro_expansion( |             .parse_macro_expansion( | ||||||
|                 sa.expand(self.db, self.wrap_node_infile(macro_call.clone()).as_ref())?, |                 sa.expansion(self.db, self.wrap_node_infile(macro_call.clone()).as_ref())?, | ||||||
|             ) |             ) | ||||||
|             .value |             .value | ||||||
|             .1 |             .1 | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ use hir_def::{ | ||||||
|     }, |     }, | ||||||
|     hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat}, |     hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat}, | ||||||
|     lang_item::LangItem, |     lang_item::LangItem, | ||||||
|     nameres::{MacroSubNs, crate_def_map}, |     nameres::{MacroSubNs, block_def_map, crate_def_map}, | ||||||
|     resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope}, |     resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope}, | ||||||
|     type_ref::{Mutability, TypeRefId}, |     type_ref::{Mutability, TypeRefId}, | ||||||
| }; | }; | ||||||
|  | @ -218,8 +218,16 @@ impl<'db> SourceAnalyzer<'db> { | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) fn expansion(&self, node: InFile<&ast::MacroCall>) -> Option<MacroCallId> { |     pub(crate) fn expansion( | ||||||
|         self.store_sm()?.expansion(node) |         &self, | ||||||
|  |         db: &dyn HirDatabase, | ||||||
|  |         macro_call: InFile<&ast::MacroCall>, | ||||||
|  |     ) -> Option<MacroCallId> { | ||||||
|  |         self.store_sm().and_then(|sm| sm.expansion(macro_call)).or_else(|| { | ||||||
|  |             let ast_id_map = db.ast_id_map(macro_call.file_id); | ||||||
|  |             let call_ast_id = macro_call.with_value(ast_id_map.ast_id(macro_call.value)); | ||||||
|  |             self.resolver.item_scopes().find_map(|scope| scope.macro_invoc(call_ast_id)) | ||||||
|  |         }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn trait_environment(&self, db: &'db dyn HirDatabase) -> Arc<TraitEnvironment> { |     fn trait_environment(&self, db: &'db dyn HirDatabase) -> Arc<TraitEnvironment> { | ||||||
|  | @ -747,17 +755,16 @@ impl<'db> SourceAnalyzer<'db> { | ||||||
| 
 | 
 | ||||||
|     pub(crate) fn resolve_macro_call( |     pub(crate) fn resolve_macro_call( | ||||||
|         &self, |         &self, | ||||||
|         db: &'db dyn HirDatabase, |         db: &dyn HirDatabase, | ||||||
|         macro_call: InFile<&ast::MacroCall>, |         macro_call: InFile<&ast::MacroCall>, | ||||||
|     ) -> Option<Macro> { |     ) -> Option<Macro> { | ||||||
|         let bs = self.store_sm()?; |         self.expansion(db, macro_call).and_then(|it| { | ||||||
|         bs.expansion(macro_call).and_then(|it| { |  | ||||||
|             // FIXME: Block def maps
 |  | ||||||
|             let def = it.lookup(db).def; |             let def = it.lookup(db).def; | ||||||
|             crate_def_map(db, def.krate) |             let def_map = match def.block { | ||||||
|                 .macro_def_to_macro_id |                 Some(block) => block_def_map(db, base_db::salsa::plumbing::FromId::from_id(block)), | ||||||
|                 .get(&def.kind.erased_ast_id()) |                 None => crate_def_map(db, def.krate), | ||||||
|                 .map(|it| (*it).into()) |             }; | ||||||
|  |             def_map.macro_def_to_macro_id.get(&def.kind.erased_ast_id()).map(|it| (*it).into()) | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -1292,18 +1299,6 @@ impl<'db> SourceAnalyzer<'db> { | ||||||
|             .collect() |             .collect() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) fn expand( |  | ||||||
|         &self, |  | ||||||
|         db: &'db dyn HirDatabase, |  | ||||||
|         macro_call: InFile<&ast::MacroCall>, |  | ||||||
|     ) -> Option<MacroCallId> { |  | ||||||
|         self.store_sm().and_then(|bs| bs.expansion(macro_call)).or_else(|| { |  | ||||||
|             self.resolver.item_scope().macro_invoc( |  | ||||||
|                 macro_call.with_value(db.ast_id_map(macro_call.file_id).ast_id(macro_call.value)), |  | ||||||
|             ) |  | ||||||
|         }) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub(crate) fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> { |     pub(crate) fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> { | ||||||
|         let infer = self.infer()?; |         let infer = self.infer()?; | ||||||
|         let expr_id = self.expr_id(record_lit.into())?; |         let expr_id = self.expr_id(record_lit.into())?; | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
| //! in [crate::completions::mod_].
 | //! in [crate::completions::mod_].
 | ||||||
| use expect_test::expect; | use expect_test::expect; | ||||||
| 
 | 
 | ||||||
| use crate::tests::{check_edit, check_with_base_items}; | use crate::tests::{check, check_edit, check_with_base_items}; | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn target_type_or_trait_in_impl_block() { | fn target_type_or_trait_in_impl_block() { | ||||||
|  | @ -308,3 +308,39 @@ fn bar() { | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | #[test] | ||||||
|  | fn expression_in_item_macro() { | ||||||
|  |     check( | ||||||
|  |         r#" | ||||||
|  | fn foo() -> u8 { 0 } | ||||||
|  | 
 | ||||||
|  | macro_rules! foo { | ||||||
|  |     ($expr:expr) => { | ||||||
|  |         const BAR: u8 = $expr; | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | foo!(f$0); | ||||||
|  |     "#,
 | ||||||
|  |         expect![[r#" | ||||||
|  |             ct BAR                   u8 | ||||||
|  |             fn foo()         fn() -> u8 | ||||||
|  |             ma foo!(…) macro_rules! foo | ||||||
|  |             bt u32                  u32 | ||||||
|  |             kw const | ||||||
|  |             kw crate:: | ||||||
|  |             kw false | ||||||
|  |             kw for | ||||||
|  |             kw if | ||||||
|  |             kw if let | ||||||
|  |             kw loop | ||||||
|  |             kw match | ||||||
|  |             kw self:: | ||||||
|  |             kw true | ||||||
|  |             kw unsafe | ||||||
|  |             kw while | ||||||
|  |             kw while let | ||||||
|  |         "#]],
 | ||||||
|  |     ); | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Chayim Refael Friedman
						Chayim Refael Friedman