Merge pull request #19905 from Veykril/push-unwwyqpwqxky

refactor: Cleanup descension stuff
This commit is contained in:
Lukas Wirth 2025-06-04 10:42:38 +00:00 committed by GitHub
commit 55b733103e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 34 deletions

View File

@ -892,7 +892,7 @@ impl<'db> SemanticsImpl<'db> {
if first == last { if first == last {
// node is just the token, so descend the token // node is just the token, so descend the token
self.descend_into_macros_impl( self.descend_into_macros_all(
InFile::new(file.file_id, first), InFile::new(file.file_id, first),
false, false,
&mut |InFile { value, .. }, _ctx| { &mut |InFile { value, .. }, _ctx| {
@ -903,23 +903,19 @@ impl<'db> SemanticsImpl<'db> {
{ {
res.push(node) res.push(node)
} }
CONTINUE_NO_BREAKS
}, },
); );
} else { } else {
// Descend first and last token, then zip them to look for the node they belong to // Descend first and last token, then zip them to look for the node they belong to
let mut scratch: SmallVec<[_; 1]> = smallvec![]; let mut scratch: SmallVec<[_; 1]> = smallvec![];
self.descend_into_macros_impl( self.descend_into_macros_all(
InFile::new(file.file_id, first), InFile::new(file.file_id, first),
false, false,
&mut |token, _ctx| { &mut |token, _ctx| scratch.push(token),
scratch.push(token);
CONTINUE_NO_BREAKS
},
); );
let mut scratch = scratch.into_iter(); let mut scratch = scratch.into_iter();
self.descend_into_macros_impl( self.descend_into_macros_all(
InFile::new(file.file_id, last), InFile::new(file.file_id, last),
false, false,
&mut |InFile { value: last, file_id: last_fid }, _ctx| { &mut |InFile { value: last, file_id: last_fid }, _ctx| {
@ -938,17 +934,18 @@ impl<'db> SemanticsImpl<'db> {
} }
} }
} }
CONTINUE_NO_BREAKS
}, },
); );
} }
res res
} }
pub fn is_inside_macro_call(&self, token: InFile<&SyntaxToken>) -> bool { /// Returns true if the given input is within a macro call.
// FIXME: Maybe `ancestors_with_macros()` is more suitable here? Currently ///
// this is only used on real (not macro) files so this is not a problem. /// Note that if this token itself is within the context of a macro expansion does not matter.
token.value.parent_ancestors().any(|ancestor| { /// That is, we strictly check if it lies inside the input of a macro call.
pub fn is_inside_macro_call(&self, token @ InFile { value, .. }: InFile<&SyntaxToken>) -> bool {
value.parent_ancestors().any(|ancestor| {
if ast::MacroCall::can_cast(ancestor.kind()) { if ast::MacroCall::can_cast(ancestor.kind()) {
return true; return true;
} }
@ -983,21 +980,17 @@ impl<'db> SemanticsImpl<'db> {
token: SyntaxToken, token: SyntaxToken,
mut cb: impl FnMut(InFile<SyntaxToken>, SyntaxContext), mut cb: impl FnMut(InFile<SyntaxToken>, SyntaxContext),
) { ) {
self.descend_into_macros_impl(self.wrap_token_infile(token), false, &mut |t, ctx| { self.descend_into_macros_all(self.wrap_token_infile(token), false, &mut |t, ctx| {
cb(t, ctx); cb(t, ctx)
CONTINUE_NO_BREAKS
}); });
} }
pub fn descend_into_macros(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> { pub fn descend_into_macros(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
let mut res = smallvec![]; let mut res = smallvec![];
self.descend_into_macros_impl( self.descend_into_macros_all(
self.wrap_token_infile(token.clone()), self.wrap_token_infile(token.clone()),
false, false,
&mut |t, _ctx| { &mut |t, _ctx| res.push(t.value),
res.push(t.value);
CONTINUE_NO_BREAKS
},
); );
if res.is_empty() { if res.is_empty() {
res.push(token); res.push(token);
@ -1011,12 +1004,11 @@ impl<'db> SemanticsImpl<'db> {
) -> SmallVec<[InFile<SyntaxToken>; 1]> { ) -> SmallVec<[InFile<SyntaxToken>; 1]> {
let mut res = smallvec![]; let mut res = smallvec![];
let token = self.wrap_token_infile(token); let token = self.wrap_token_infile(token);
self.descend_into_macros_impl(token.clone(), true, &mut |t, ctx| { self.descend_into_macros_all(token.clone(), true, &mut |t, ctx| {
if !ctx.is_opaque(self.db) { if !ctx.is_opaque(self.db) {
// Don't descend into opaque contexts // Don't descend into opaque contexts
res.push(t); res.push(t);
} }
CONTINUE_NO_BREAKS
}); });
if res.is_empty() { if res.is_empty() {
res.push(token); res.push(token);
@ -1099,6 +1091,18 @@ impl<'db> SemanticsImpl<'db> {
.unwrap_or(token) .unwrap_or(token)
} }
fn descend_into_macros_all(
&self,
token: InFile<SyntaxToken>,
always_descend_into_derives: bool,
f: &mut dyn FnMut(InFile<SyntaxToken>, SyntaxContext),
) {
self.descend_into_macros_impl(token, always_descend_into_derives, &mut |tok, ctx| {
f(tok, ctx);
CONTINUE_NO_BREAKS
});
}
fn descend_into_macros_impl<T>( fn descend_into_macros_impl<T>(
&self, &self,
InFile { value: token, file_id }: InFile<SyntaxToken>, InFile { value: token, file_id }: InFile<SyntaxToken>,
@ -1467,13 +1471,21 @@ impl<'db> SemanticsImpl<'db> {
} }
/// Iterates the ancestors of the given node, climbing up macro expansions while doing so. /// Iterates the ancestors of the given node, climbing up macro expansions while doing so.
// FIXME: Replace with `ancestors_with_macros_file` when all usages are updated.
pub fn ancestors_with_macros( pub fn ancestors_with_macros(
&self, &self,
node: SyntaxNode, node: SyntaxNode,
) -> impl Iterator<Item = SyntaxNode> + Clone + '_ { ) -> impl Iterator<Item = SyntaxNode> + Clone + '_ {
let node = self.find_file(&node); let node = self.find_file(&node);
iter::successors(Some(node.cloned()), move |&InFile { file_id, ref value }| { self.ancestors_with_macros_file(node.cloned()).map(|it| it.value)
match value.parent() { }
/// Iterates the ancestors of the given node, climbing up macro expansions while doing so.
pub fn ancestors_with_macros_file(
&self,
node: InFile<SyntaxNode>,
) -> impl Iterator<Item = InFile<SyntaxNode>> + Clone + '_ {
iter::successors(Some(node), move |&InFile { file_id, ref value }| match value.parent() {
Some(parent) => Some(InFile::new(file_id, parent)), Some(parent) => Some(InFile::new(file_id, parent)),
None => { None => {
let macro_file = file_id.macro_file()?; let macro_file = file_id.macro_file()?;
@ -1483,9 +1495,7 @@ impl<'db> SemanticsImpl<'db> {
expansion_info.arg().map(|node| node?.parent()).transpose() expansion_info.arg().map(|node| node?.parent()).transpose()
}) })
} }
}
}) })
.map(|it| it.value)
} }
pub fn ancestors_at_offset_with_macros( pub fn ancestors_at_offset_with_macros(

View File

@ -411,6 +411,7 @@ impl SourceToDefCtx<'_, '_> {
.map(|&(attr_id, call_id, ref ids)| (attr_id, call_id, &**ids)) .map(|&(attr_id, call_id, ref ids)| (attr_id, call_id, &**ids))
} }
// FIXME: Make this more fine grained! This should be a `adt_has_derives`!
pub(super) fn file_of_adt_has_derives(&mut self, adt: InFile<&ast::Adt>) -> bool { pub(super) fn file_of_adt_has_derives(&mut self, adt: InFile<&ast::Adt>) -> bool {
self.dyn_map(adt).as_ref().is_some_and(|map| !map[keys::DERIVE_MACRO_CALL].is_empty()) self.dyn_map(adt).as_ref().is_some_and(|map| !map[keys::DERIVE_MACRO_CALL].is_empty())
} }