@@ -2,13 +2,13 @@ use hir::Semantics;
2
2
use ide_db:: {
3
3
base_db:: FilePosition ,
4
4
defs:: Definition ,
5
- helpers:: pick_best_token,
5
+ helpers:: { for_each_break_expr , for_each_tail_expr , pick_best_token} ,
6
6
search:: { FileReference , ReferenceAccess , SearchScope } ,
7
7
RootDatabase ,
8
8
} ;
9
9
use syntax:: {
10
10
ast:: { self , LoopBodyOwner } ,
11
- match_ast, AstNode , SyntaxNode , SyntaxToken , TextRange , WalkEvent , T ,
11
+ match_ast, AstNode , SyntaxNode , SyntaxToken , TextRange , T ,
12
12
} ;
13
13
14
14
use crate :: { display:: TryToNav , references, NavigationTarget } ;
@@ -95,7 +95,7 @@ fn highlight_exit_points(
95
95
) -> Option < Vec < HighlightedRange > > {
96
96
let mut highlights = Vec :: new ( ) ;
97
97
let body = body?;
98
- walk ( & body , & mut |expr| match expr {
98
+ body . walk ( & mut |expr| match expr {
99
99
ast:: Expr :: ReturnExpr ( expr) => {
100
100
if let Some ( token) = expr. return_token ( ) {
101
101
highlights. push ( HighlightedRange { access : None , range : token. text_range ( ) } ) ;
@@ -120,7 +120,7 @@ fn highlight_exit_points(
120
120
} ;
121
121
122
122
if let Some ( tail) = tail {
123
- for_each_inner_tail ( & tail, & mut |tail| {
123
+ for_each_tail_expr ( & tail, & mut |tail| {
124
124
let range = match tail {
125
125
ast:: Expr :: BreakExpr ( b) => b
126
126
. break_token ( )
@@ -161,7 +161,7 @@ fn highlight_break_points(token: SyntaxToken) -> Option<Vec<HighlightedRange>> {
161
161
label. as_ref ( ) . map ( |it| it. syntax ( ) . text_range ( ) ) ,
162
162
) ;
163
163
highlights. extend ( range. map ( |range| HighlightedRange { access : None , range } ) ) ;
164
- for_each_break ( label, body, & mut |break_| {
164
+ for_each_break_expr ( label, body, & mut |break_| {
165
165
let range = cover_range (
166
166
break_. break_token ( ) . map ( |it| it. text_range ( ) ) ,
167
167
break_. lifetime ( ) . map ( |it| it. syntax ( ) . text_range ( ) ) ,
@@ -216,7 +216,7 @@ fn highlight_yield_points(token: SyntaxToken) -> Option<Vec<HighlightedRange>> {
216
216
let mut highlights = Vec :: new ( ) ;
217
217
highlights. push ( HighlightedRange { access : None , range : async_token?. text_range ( ) } ) ;
218
218
if let Some ( body) = body {
219
- walk ( & body , & mut |expr| {
219
+ body . walk ( & mut |expr| {
220
220
if let ast:: Expr :: AwaitExpr ( expr) = expr {
221
221
if let Some ( token) = expr. await_token ( ) {
222
222
highlights
@@ -240,156 +240,6 @@ fn highlight_yield_points(token: SyntaxToken) -> Option<Vec<HighlightedRange>> {
240
240
None
241
241
}
242
242
243
- /// Preorder walk all the expression's child expressions
244
- fn walk ( expr : & ast:: Expr , cb : & mut dyn FnMut ( ast:: Expr ) ) {
245
- let mut preorder = expr. syntax ( ) . preorder ( ) ;
246
- while let Some ( event) = preorder. next ( ) {
247
- let node = match event {
248
- WalkEvent :: Enter ( node) => node,
249
- WalkEvent :: Leave ( _) => continue ,
250
- } ;
251
- match ast:: Stmt :: cast ( node. clone ( ) ) {
252
- // recursively walk the initializer, skipping potential const pat expressions
253
- // lets statements aren't usually nested too deeply so this is fine to recurse on
254
- Some ( ast:: Stmt :: LetStmt ( l) ) => {
255
- if let Some ( expr) = l. initializer ( ) {
256
- walk ( & expr, cb) ;
257
- }
258
- preorder. skip_subtree ( ) ;
259
- }
260
- // Don't skip subtree since we want to process the expression child next
261
- Some ( ast:: Stmt :: ExprStmt ( _) ) => ( ) ,
262
- // skip inner items which might have their own expressions
263
- Some ( ast:: Stmt :: Item ( _) ) => preorder. skip_subtree ( ) ,
264
- None => {
265
- if let Some ( expr) = ast:: Expr :: cast ( node) {
266
- let is_different_context = match & expr {
267
- ast:: Expr :: EffectExpr ( effect) => {
268
- matches ! (
269
- effect. effect( ) ,
270
- ast:: Effect :: Async ( _) | ast:: Effect :: Try ( _) | ast:: Effect :: Const ( _)
271
- )
272
- }
273
- ast:: Expr :: ClosureExpr ( __) => true ,
274
- _ => false ,
275
- } ;
276
- cb ( expr) ;
277
- if is_different_context {
278
- preorder. skip_subtree ( ) ;
279
- }
280
- } else {
281
- preorder. skip_subtree ( ) ;
282
- }
283
- }
284
- }
285
- }
286
- }
287
-
288
- // FIXME: doesn't account for labeled breaks in labeled blocks
289
- fn for_each_inner_tail ( expr : & ast:: Expr , cb : & mut dyn FnMut ( & ast:: Expr ) ) {
290
- match expr {
291
- ast:: Expr :: BlockExpr ( b) => {
292
- if let Some ( e) = b. tail_expr ( ) {
293
- for_each_inner_tail ( & e, cb) ;
294
- }
295
- }
296
- ast:: Expr :: EffectExpr ( e) => match e. effect ( ) {
297
- ast:: Effect :: Label ( label) => {
298
- for_each_break ( Some ( label) , e. block_expr ( ) , & mut |b| cb ( & ast:: Expr :: BreakExpr ( b) ) ) ;
299
- if let Some ( b) = e. block_expr ( ) {
300
- for_each_inner_tail ( & ast:: Expr :: BlockExpr ( b) , cb) ;
301
- }
302
- }
303
- ast:: Effect :: Unsafe ( _) => {
304
- if let Some ( e) = e. block_expr ( ) . and_then ( |b| b. tail_expr ( ) ) {
305
- for_each_inner_tail ( & e, cb) ;
306
- }
307
- }
308
- ast:: Effect :: Async ( _) | ast:: Effect :: Try ( _) | ast:: Effect :: Const ( _) => cb ( expr) ,
309
- } ,
310
- ast:: Expr :: IfExpr ( if_) => {
311
- if_. blocks ( ) . for_each ( |block| for_each_inner_tail ( & ast:: Expr :: BlockExpr ( block) , cb) )
312
- }
313
- ast:: Expr :: LoopExpr ( l) => {
314
- for_each_break ( l. label ( ) , l. loop_body ( ) , & mut |b| cb ( & ast:: Expr :: BreakExpr ( b) ) )
315
- }
316
- ast:: Expr :: MatchExpr ( m) => {
317
- if let Some ( arms) = m. match_arm_list ( ) {
318
- arms. arms ( ) . filter_map ( |arm| arm. expr ( ) ) . for_each ( |e| for_each_inner_tail ( & e, cb) ) ;
319
- }
320
- }
321
- ast:: Expr :: ArrayExpr ( _)
322
- | ast:: Expr :: AwaitExpr ( _)
323
- | ast:: Expr :: BinExpr ( _)
324
- | ast:: Expr :: BoxExpr ( _)
325
- | ast:: Expr :: BreakExpr ( _)
326
- | ast:: Expr :: CallExpr ( _)
327
- | ast:: Expr :: CastExpr ( _)
328
- | ast:: Expr :: ClosureExpr ( _)
329
- | ast:: Expr :: ContinueExpr ( _)
330
- | ast:: Expr :: FieldExpr ( _)
331
- | ast:: Expr :: ForExpr ( _)
332
- | ast:: Expr :: IndexExpr ( _)
333
- | ast:: Expr :: Literal ( _)
334
- | ast:: Expr :: MacroCall ( _)
335
- | ast:: Expr :: MacroStmts ( _)
336
- | ast:: Expr :: MethodCallExpr ( _)
337
- | ast:: Expr :: ParenExpr ( _)
338
- | ast:: Expr :: PathExpr ( _)
339
- | ast:: Expr :: PrefixExpr ( _)
340
- | ast:: Expr :: RangeExpr ( _)
341
- | ast:: Expr :: RecordExpr ( _)
342
- | ast:: Expr :: RefExpr ( _)
343
- | ast:: Expr :: ReturnExpr ( _)
344
- | ast:: Expr :: TryExpr ( _)
345
- | ast:: Expr :: TupleExpr ( _)
346
- | ast:: Expr :: WhileExpr ( _)
347
- | ast:: Expr :: YieldExpr ( _) => cb ( expr) ,
348
- }
349
- }
350
-
351
- fn for_each_break (
352
- label : Option < ast:: Label > ,
353
- body : Option < ast:: BlockExpr > ,
354
- cb : & mut dyn FnMut ( ast:: BreakExpr ) ,
355
- ) {
356
- let label = label. and_then ( |lbl| lbl. lifetime ( ) ) ;
357
- let mut depth = 0 ;
358
- if let Some ( b) = body {
359
- let preorder = & mut b. syntax ( ) . preorder ( ) ;
360
- let ev_as_expr = |ev| match ev {
361
- WalkEvent :: Enter ( it) => Some ( WalkEvent :: Enter ( ast:: Expr :: cast ( it) ?) ) ,
362
- WalkEvent :: Leave ( it) => Some ( WalkEvent :: Leave ( ast:: Expr :: cast ( it) ?) ) ,
363
- } ;
364
- let eq_label = |lt : Option < ast:: Lifetime > | {
365
- lt. zip ( label. as_ref ( ) ) . map_or ( false , |( lt, lbl) | lt. text ( ) == lbl. text ( ) )
366
- } ;
367
- while let Some ( node) = preorder. find_map ( ev_as_expr) {
368
- match node {
369
- WalkEvent :: Enter ( expr) => match expr {
370
- ast:: Expr :: LoopExpr ( _) | ast:: Expr :: WhileExpr ( _) | ast:: Expr :: ForExpr ( _) => {
371
- depth += 1
372
- }
373
- ast:: Expr :: EffectExpr ( e) if e. label ( ) . is_some ( ) => depth += 1 ,
374
- ast:: Expr :: BreakExpr ( b)
375
- if ( depth == 0 && b. lifetime ( ) . is_none ( ) ) || eq_label ( b. lifetime ( ) ) =>
376
- {
377
- cb ( b) ;
378
- }
379
- _ => ( ) ,
380
- } ,
381
- WalkEvent :: Leave ( expr) => match expr {
382
- ast:: Expr :: LoopExpr ( _) | ast:: Expr :: WhileExpr ( _) | ast:: Expr :: ForExpr ( _) => {
383
- depth -= 1
384
- }
385
- ast:: Expr :: EffectExpr ( e) if e. label ( ) . is_some ( ) => depth -= 1 ,
386
- _ => ( ) ,
387
- } ,
388
- }
389
- }
390
- }
391
- }
392
-
393
243
fn cover_range ( r0 : Option < TextRange > , r1 : Option < TextRange > ) -> Option < TextRange > {
394
244
match ( r0, r1) {
395
245
( Some ( r0) , Some ( r1) ) => Some ( r0. cover ( r1) ) ,
0 commit comments