@@ -59,7 +59,7 @@ pub(super) fn expand_and_analyze(
59
59
// make the offset point to the start of the original token, as that is what the
60
60
// intermediate offsets calculated in expansion always points to
61
61
let offset = offset - relative_offset;
62
- let expansion = expand (
62
+ let expansion = expand_maybe_stop (
63
63
sema,
64
64
original_file. clone ( ) ,
65
65
speculative_file. clone ( ) ,
@@ -118,31 +118,56 @@ fn token_at_offset_ignore_whitespace(file: &SyntaxNode, offset: TextSize) -> Opt
118
118
/// that we check, we subtract `COMPLETION_MARKER.len()`. This may not be accurate because proc macros
119
119
/// can insert the text of the completion marker in other places while removing the span, but this is
120
120
/// the best we can do.
121
- fn expand (
121
+ fn expand_maybe_stop (
122
122
sema : & Semantics < ' _ , RootDatabase > ,
123
123
original_file : SyntaxNode ,
124
124
speculative_file : SyntaxNode ,
125
125
original_offset : TextSize ,
126
126
fake_ident_token : SyntaxToken ,
127
127
relative_offset : TextSize ,
128
128
) -> 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
+ }
130
139
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.
131
143
// Left biased since there may already be an identifier token there, and we appended to it.
132
144
if !sema. might_be_inside_macro_call ( & fake_ident_token)
133
145
&& token_at_offset_ignore_whitespace ( & original_file, original_offset + relative_offset)
134
146
. is_some_and ( |original_token| !sema. might_be_inside_macro_call ( & original_token) )
135
147
{
136
148
// Recursion base case.
137
- return Some ( ExpansionResult {
149
+ Some ( ExpansionResult {
138
150
original_file,
139
151
speculative_file,
140
152
original_offset,
141
153
speculative_offset : fake_ident_token. text_range ( ) . start ( ) ,
142
154
fake_ident_token,
143
155
derive_ctx : None ,
144
- } ) ;
156
+ } )
157
+ } else {
158
+ None
145
159
}
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 ( ) ;
146
171
147
172
let parent_item =
148
173
|item : & ast:: Item | item. syntax ( ) . ancestors ( ) . skip ( 1 ) . find_map ( ast:: Item :: cast) ;
@@ -197,7 +222,7 @@ fn expand(
197
222
// stop here to prevent problems from happening
198
223
return None ;
199
224
}
200
- let result = expand (
225
+ let result = expand_maybe_stop (
201
226
sema,
202
227
actual_expansion. clone ( ) ,
203
228
fake_expansion. clone ( ) ,
@@ -317,7 +342,7 @@ fn expand(
317
342
// stop here to prevent problems from happening
318
343
return None ;
319
344
}
320
- let result = expand (
345
+ let result = expand_maybe_stop (
321
346
sema,
322
347
actual_expansion. clone ( ) ,
323
348
fake_expansion. clone ( ) ,
@@ -386,7 +411,7 @@ fn expand(
386
411
// stop here to prevent problems from happening
387
412
return None ;
388
413
}
389
- let result = expand (
414
+ let result = expand_maybe_stop (
390
415
sema,
391
416
actual_expansion. clone ( ) ,
392
417
fake_expansion. clone ( ) ,
0 commit comments