@@ -281,99 +281,95 @@ fn highlight_references(
281
281
}
282
282
}
283
283
284
- // If `file_id` is None,
285
- pub ( crate ) fn highlight_exit_points (
284
+ fn hl_exit_points (
286
285
sema : & Semantics < ' _ , RootDatabase > ,
287
- token : SyntaxToken ,
288
- ) -> FxHashMap < EditionedFileId , Vec < HighlightedRange > > {
289
- fn hl (
290
- sema : & Semantics < ' _ , RootDatabase > ,
291
- def_token : Option < SyntaxToken > ,
292
- body : ast:: Expr ,
293
- ) -> Option < FxHashMap < EditionedFileId , FxHashSet < HighlightedRange > > > {
294
- let mut highlights: FxHashMap < EditionedFileId , FxHashSet < _ > > = FxHashMap :: default ( ) ;
286
+ def_token : Option < SyntaxToken > ,
287
+ body : ast:: Expr ,
288
+ ) -> Option < FxHashMap < EditionedFileId , FxHashSet < HighlightedRange > > > {
289
+ let mut highlights: FxHashMap < EditionedFileId , FxHashSet < _ > > = FxHashMap :: default ( ) ;
290
+
291
+ let mut push_to_highlights = |file_id, range| {
292
+ if let Some ( FileRange { file_id, range } ) = original_frange ( sema. db , file_id, range) {
293
+ let hrange = HighlightedRange { category : ReferenceCategory :: empty ( ) , range } ;
294
+ highlights. entry ( file_id) . or_default ( ) . insert ( hrange) ;
295
+ }
296
+ } ;
295
297
296
- let mut push_to_highlights = |file_id, range| {
297
- if let Some ( FileRange { file_id, range } ) = original_frange ( sema. db , file_id, range) {
298
- let hrange = HighlightedRange { category : ReferenceCategory :: empty ( ) , range } ;
299
- highlights. entry ( file_id) . or_default ( ) . insert ( hrange) ;
298
+ if let Some ( tok) = def_token {
299
+ let file_id = sema. hir_file_for ( & tok. parent ( ) ?) ;
300
+ let range = Some ( tok. text_range ( ) ) ;
301
+ push_to_highlights ( file_id, range) ;
302
+ }
303
+
304
+ WalkExpandedExprCtx :: new ( sema) . walk ( & body, & mut |_, expr| {
305
+ let file_id = sema. hir_file_for ( expr. syntax ( ) ) ;
306
+
307
+ let range = match & expr {
308
+ ast:: Expr :: TryExpr ( try_) => try_. question_mark_token ( ) . map ( |token| token. text_range ( ) ) ,
309
+ ast:: Expr :: MethodCallExpr ( _) | ast:: Expr :: CallExpr ( _) | ast:: Expr :: MacroExpr ( _)
310
+ if sema. type_of_expr ( & expr) . map_or ( false , |ty| ty. original . is_never ( ) ) =>
311
+ {
312
+ Some ( expr. syntax ( ) . text_range ( ) )
300
313
}
314
+ _ => None ,
301
315
} ;
302
316
303
- if let Some ( tok) = def_token {
304
- let file_id = sema. hir_file_for ( & tok. parent ( ) ?) ;
305
- let range = Some ( tok. text_range ( ) ) ;
306
- push_to_highlights ( file_id, range) ;
307
- }
317
+ push_to_highlights ( file_id, range) ;
318
+ } ) ;
308
319
309
- WalkExpandedExprCtx :: new ( sema) . walk ( & body, & mut |_, expr| {
320
+ // We should handle `return` separately, because when it is used in a `try` block,
321
+ // it will exit the outside function instead of the block itself.
322
+ WalkExpandedExprCtx :: new ( sema)
323
+ . with_check_ctx ( & WalkExpandedExprCtx :: is_async_const_block_or_closure)
324
+ . walk ( & body, & mut |_, expr| {
310
325
let file_id = sema. hir_file_for ( expr. syntax ( ) ) ;
311
326
312
327
let range = match & expr {
313
- ast:: Expr :: TryExpr ( try_) => {
314
- try_. question_mark_token ( ) . map ( |token| token. text_range ( ) )
315
- }
316
- ast:: Expr :: MethodCallExpr ( _) | ast:: Expr :: CallExpr ( _) | ast:: Expr :: MacroExpr ( _)
317
- if sema. type_of_expr ( & expr) . map_or ( false , |ty| ty. original . is_never ( ) ) =>
318
- {
319
- Some ( expr. syntax ( ) . text_range ( ) )
320
- }
328
+ ast:: Expr :: ReturnExpr ( expr) => expr. return_token ( ) . map ( |token| token. text_range ( ) ) ,
321
329
_ => None ,
322
330
} ;
323
331
324
332
push_to_highlights ( file_id, range) ;
325
333
} ) ;
326
334
327
- // We should handle `return` separately, because when it is used in a `try` block,
328
- // it will exit the outside function instead of the block itself.
329
- WalkExpandedExprCtx :: new ( sema)
330
- . with_check_ctx ( & WalkExpandedExprCtx :: is_async_const_block_or_closure)
331
- . walk ( & body, & mut |_, expr| {
332
- let file_id = sema. hir_file_for ( expr. syntax ( ) ) ;
333
-
334
- let range = match & expr {
335
- ast:: Expr :: ReturnExpr ( expr) => {
336
- expr. return_token ( ) . map ( |token| token. text_range ( ) )
337
- }
338
- _ => None ,
339
- } ;
340
-
341
- push_to_highlights ( file_id, range) ;
342
- } ) ;
343
-
344
- let tail = match body {
345
- ast:: Expr :: BlockExpr ( b) => b. tail_expr ( ) ,
346
- e => Some ( e) ,
347
- } ;
335
+ let tail = match body {
336
+ ast:: Expr :: BlockExpr ( b) => b. tail_expr ( ) ,
337
+ e => Some ( e) ,
338
+ } ;
348
339
349
- if let Some ( tail) = tail {
350
- for_each_tail_expr ( & tail, & mut |tail| {
351
- let file_id = sema. hir_file_for ( tail. syntax ( ) ) ;
352
- let range = match tail {
353
- ast:: Expr :: BreakExpr ( b) => b
354
- . break_token ( )
355
- . map_or_else ( || tail. syntax ( ) . text_range ( ) , |tok| tok. text_range ( ) ) ,
356
- _ => tail. syntax ( ) . text_range ( ) ,
357
- } ;
358
- push_to_highlights ( file_id, Some ( range) ) ;
359
- } ) ;
360
- }
361
- Some ( highlights)
340
+ if let Some ( tail) = tail {
341
+ for_each_tail_expr ( & tail, & mut |tail| {
342
+ let file_id = sema. hir_file_for ( tail. syntax ( ) ) ;
343
+ let range = match tail {
344
+ ast:: Expr :: BreakExpr ( b) => b
345
+ . break_token ( )
346
+ . map_or_else ( || tail. syntax ( ) . text_range ( ) , |tok| tok. text_range ( ) ) ,
347
+ _ => tail. syntax ( ) . text_range ( ) ,
348
+ } ;
349
+ push_to_highlights ( file_id, Some ( range) ) ;
350
+ } ) ;
362
351
}
352
+ Some ( highlights)
353
+ }
363
354
355
+ // If `file_id` is None,
356
+ pub ( crate ) fn highlight_exit_points (
357
+ sema : & Semantics < ' _ , RootDatabase > ,
358
+ token : SyntaxToken ,
359
+ ) -> FxHashMap < EditionedFileId , Vec < HighlightedRange > > {
364
360
let mut res = FxHashMap :: default ( ) ;
365
361
for def in goto_definition:: find_fn_or_blocks ( sema, & token) {
366
362
let new_map = match_ast ! {
367
363
match def {
368
- ast:: Fn ( fn_) => fn_. body( ) . and_then( |body| hl ( sema, fn_. fn_token( ) , body. into( ) ) ) ,
364
+ ast:: Fn ( fn_) => fn_. body( ) . and_then( |body| hl_exit_points ( sema, fn_. fn_token( ) , body. into( ) ) ) ,
369
365
ast:: ClosureExpr ( closure) => {
370
366
let pipe_tok = closure. param_list( ) . and_then( |p| p. pipe_token( ) ) ;
371
- closure. body( ) . and_then( |body| hl ( sema, pipe_tok, body) )
367
+ closure. body( ) . and_then( |body| hl_exit_points ( sema, pipe_tok, body) )
372
368
} ,
373
369
ast:: BlockExpr ( blk) => match blk. modifier( ) {
374
- Some ( ast:: BlockModifier :: Async ( t) ) => hl ( sema, Some ( t) , blk. into( ) ) ,
370
+ Some ( ast:: BlockModifier :: Async ( t) ) => hl_exit_points ( sema, Some ( t) , blk. into( ) ) ,
375
371
Some ( ast:: BlockModifier :: Try ( t) ) if token. kind( ) != T ![ return ] => {
376
- hl ( sema, Some ( t) , blk. into( ) )
372
+ hl_exit_points ( sema, Some ( t) , blk. into( ) )
377
373
} ,
378
374
_ => continue ,
379
375
} ,
@@ -520,6 +516,12 @@ pub(crate) fn highlight_yield_points(
520
516
if block_expr. async_token( ) . is_none( ) {
521
517
continue ;
522
518
}
519
+
520
+ // Async blocks act similar to closures. So we want to
521
+ // highlight their exit points too.
522
+ let exit_points = hl_exit_points( sema, block_expr. async_token( ) , block_expr. clone( ) . into( ) ) ;
523
+ merge_map( & mut res, exit_points) ;
524
+
523
525
hl( sema, block_expr. async_token( ) , Some ( block_expr. into( ) ) )
524
526
} ,
525
527
ast:: ClosureExpr ( closure) => hl( sema, closure. async_token( ) , closure. body( ) ) ,
@@ -876,6 +878,27 @@ pub async$0 fn foo() {
876
878
) ;
877
879
}
878
880
881
+ #[ test]
882
+ fn test_hl_exit_points_of_async_blocks ( ) {
883
+ check (
884
+ r#"
885
+ pub fn foo() {
886
+ let x = async$0 {
887
+ // ^^^^^
888
+ 0.await;
889
+ // ^^^^^
890
+ 0?;
891
+ // ^
892
+ return 0;
893
+ // ^^^^^^
894
+ 0
895
+ // ^
896
+ };
897
+ }
898
+ "# ,
899
+ ) ;
900
+ }
901
+
879
902
#[ test]
880
903
fn test_hl_let_else_yield_points ( ) {
881
904
check (
@@ -925,11 +948,10 @@ async fn foo() {
925
948
async fn foo() {
926
949
(async {
927
950
// ^^^^^
928
- (async {
929
- 0.await
930
- }).await$0 }
931
- // ^^^^^
932
- ).await;
951
+ (async { 0.await }).await$0
952
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^
953
+ // ^^^^^
954
+ }).await;
933
955
}
934
956
"# ,
935
957
) ;
0 commit comments