@@ -59,7 +59,7 @@ pub(super) fn expand_and_analyze(
5959 // make the offset point to the start of the original token, as that is what the
6060 // intermediate offsets calculated in expansion always points to
6161 let offset = offset - relative_offset;
62- let expansion = expand (
62+ let expansion = expand_maybe_stop (
6363 sema,
6464 original_file. clone ( ) ,
6565 speculative_file. clone ( ) ,
@@ -118,31 +118,56 @@ fn token_at_offset_ignore_whitespace(file: &SyntaxNode, offset: TextSize) -> Opt
118118/// that we check, we subtract `COMPLETION_MARKER.len()`. This may not be accurate because proc macros
119119/// can insert the text of the completion marker in other places while removing the span, but this is
120120/// the best we can do.
121- fn expand (
121+ fn expand_maybe_stop (
122122 sema : & Semantics < ' _ , RootDatabase > ,
123123 original_file : SyntaxNode ,
124124 speculative_file : SyntaxNode ,
125125 original_offset : TextSize ,
126126 fake_ident_token : SyntaxToken ,
127127 relative_offset : TextSize ,
128128) -> Option < ExpansionResult > {
129- let _p = tracing:: info_span!( "CompletionContext::expand" ) . entered ( ) ;
129+ if let result @ Some ( _) = expand (
130+ sema,
131+ original_file. clone ( ) ,
132+ speculative_file. clone ( ) ,
133+ original_offset,
134+ fake_ident_token. clone ( ) ,
135+ relative_offset,
136+ ) {
137+ return result;
138+ }
130139
140+ // This needs to come after the recursive call, because our "inside macro" detection is subtly wrong
141+ // with regard to attribute macros named `test` that are not std's test. So hopefully we will expand
142+ // them successfully above and be able to analyze.
131143 // Left biased since there may already be an identifier token there, and we appended to it.
132144 if !sema. might_be_inside_macro_call ( & fake_ident_token)
133145 && token_at_offset_ignore_whitespace ( & original_file, original_offset + relative_offset)
134146 . is_some_and ( |original_token| !sema. might_be_inside_macro_call ( & original_token) )
135147 {
136148 // Recursion base case.
137- return Some ( ExpansionResult {
149+ Some ( ExpansionResult {
138150 original_file,
139151 speculative_file,
140152 original_offset,
141153 speculative_offset : fake_ident_token. text_range ( ) . start ( ) ,
142154 fake_ident_token,
143155 derive_ctx : None ,
144- } ) ;
156+ } )
157+ } else {
158+ None
145159 }
160+ }
161+
162+ fn expand (
163+ sema : & Semantics < ' _ , RootDatabase > ,
164+ original_file : SyntaxNode ,
165+ speculative_file : SyntaxNode ,
166+ original_offset : TextSize ,
167+ fake_ident_token : SyntaxToken ,
168+ relative_offset : TextSize ,
169+ ) -> Option < ExpansionResult > {
170+ let _p = tracing:: info_span!( "CompletionContext::expand" ) . entered ( ) ;
146171
147172 let parent_item =
148173 |item : & ast:: Item | item. syntax ( ) . ancestors ( ) . skip ( 1 ) . find_map ( ast:: Item :: cast) ;
@@ -197,7 +222,7 @@ fn expand(
197222 // stop here to prevent problems from happening
198223 return None ;
199224 }
200- let result = expand (
225+ let result = expand_maybe_stop (
201226 sema,
202227 actual_expansion. clone ( ) ,
203228 fake_expansion. clone ( ) ,
@@ -317,7 +342,7 @@ fn expand(
317342 // stop here to prevent problems from happening
318343 return None ;
319344 }
320- let result = expand (
345+ let result = expand_maybe_stop (
321346 sema,
322347 actual_expansion. clone ( ) ,
323348 fake_expansion. clone ( ) ,
@@ -386,7 +411,7 @@ fn expand(
386411 // stop here to prevent problems from happening
387412 return None ;
388413 }
389- let result = expand (
414+ let result = expand_maybe_stop (
390415 sema,
391416 actual_expansion. clone ( ) ,
392417 fake_expansion. clone ( ) ,
0 commit comments