Skip to content

Commit

Permalink
In completion's expand, consider recursion stop condition (when we're…
Browse files Browse the repository at this point in the history
… not inside a macro call anymore) *after* the recursive call instead of before it

This is because our detection is imperfect, and miss some cases such as an impersonating `test` macro, so we hope we'll expand successfully in this case.
  • Loading branch information
ChayimFriedman2 committed Jan 26, 2025
1 parent a7cbe4b commit 1360b4c
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub(super) fn expand_and_analyze(
// make the offset point to the start of the original token, as that is what the
// intermediate offsets calculated in expansion always points to
let offset = offset - relative_offset;
let expansion = expand(
let expansion = expand_maybe_stop(
sema,
original_file.clone(),
speculative_file.clone(),
Expand Down Expand Up @@ -118,31 +118,56 @@ fn token_at_offset_ignore_whitespace(file: &SyntaxNode, offset: TextSize) -> Opt
/// that we check, we subtract `COMPLETION_MARKER.len()`. This may not be accurate because proc macros
/// can insert the text of the completion marker in other places while removing the span, but this is
/// the best we can do.
fn expand(
fn expand_maybe_stop(
sema: &Semantics<'_, RootDatabase>,
original_file: SyntaxNode,
speculative_file: SyntaxNode,
original_offset: TextSize,
fake_ident_token: SyntaxToken,
relative_offset: TextSize,
) -> Option<ExpansionResult> {
let _p = tracing::info_span!("CompletionContext::expand").entered();
if let result @ Some(_) = expand(
sema,
original_file.clone(),
speculative_file.clone(),
original_offset,
fake_ident_token.clone(),
relative_offset,
) {
return result;
}

// This needs to come after the recursive call, because our "inside macro" detection is subtly wrong
// with regard to attribute macros named `test` that are not std's test. So hopefully we will expand
// them successfully above and be able to analyze.
// Left biased since there may already be an identifier token there, and we appended to it.
if !sema.might_be_inside_macro_call(&fake_ident_token)
&& token_at_offset_ignore_whitespace(&original_file, original_offset + relative_offset)
.is_some_and(|original_token| !sema.might_be_inside_macro_call(&original_token))
{
// Recursion base case.
return Some(ExpansionResult {
Some(ExpansionResult {
original_file,
speculative_file,
original_offset,
speculative_offset: fake_ident_token.text_range().start(),
fake_ident_token,
derive_ctx: None,
});
})
} else {
None
}
}

fn expand(
sema: &Semantics<'_, RootDatabase>,
original_file: SyntaxNode,
speculative_file: SyntaxNode,
original_offset: TextSize,
fake_ident_token: SyntaxToken,
relative_offset: TextSize,
) -> Option<ExpansionResult> {
let _p = tracing::info_span!("CompletionContext::expand").entered();

let parent_item =
|item: &ast::Item| item.syntax().ancestors().skip(1).find_map(ast::Item::cast);
Expand Down Expand Up @@ -197,7 +222,7 @@ fn expand(
// stop here to prevent problems from happening
return None;
}
let result = expand(
let result = expand_maybe_stop(
sema,
actual_expansion.clone(),
fake_expansion.clone(),
Expand Down Expand Up @@ -317,7 +342,7 @@ fn expand(
// stop here to prevent problems from happening
return None;
}
let result = expand(
let result = expand_maybe_stop(
sema,
actual_expansion.clone(),
fake_expansion.clone(),
Expand Down Expand Up @@ -386,7 +411,7 @@ fn expand(
// stop here to prevent problems from happening
return None;
}
let result = expand(
let result = expand_maybe_stop(
sema,
actual_expansion.clone(),
fake_expansion.clone(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1986,3 +1986,53 @@ fn foo() {
"#]],
);
}

#[test]
fn non_std_test_attr_macro() {
check(
r#"
//- proc_macros: identity
use proc_macros::identity as test;
#[test]
fn foo() {
$0
}
"#,
expect![[r#"
fn foo() fn()
md proc_macros
bt u32 u32
kw async
kw const
kw crate::
kw enum
kw extern
kw false
kw fn
kw for
kw if
kw if let
kw impl
kw let
kw loop
kw match
kw mod
kw return
kw self::
kw static
kw struct
kw trait
kw true
kw type
kw union
kw unsafe
kw use
kw while
kw while let
sn macro_rules
sn pd
sn ppd
"#]],
);
}

0 comments on commit 1360b4c

Please sign in to comment.