mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-29 10:58:02 +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