@@ -5,7 +5,7 @@ use rustc_hash::FxHashMap;
5
5
6
6
use ruff_python_ast:: helpers:: from_relative_import;
7
7
use ruff_python_ast:: name:: { QualifiedName , UnqualifiedName } ;
8
- use ruff_python_ast:: { self as ast, Expr , Operator , Stmt } ;
8
+ use ruff_python_ast:: { self as ast, Expr , ExprContext , Operator , Stmt } ;
9
9
use ruff_python_stdlib:: path:: is_python_stub_file;
10
10
use ruff_text_size:: { Ranged , TextRange , TextSize } ;
11
11
@@ -271,7 +271,7 @@ impl<'a> SemanticModel<'a> {
271
271
. get ( symbol)
272
272
. map_or ( true , |binding_id| {
273
273
// Treat the deletion of a name as a reference to that name.
274
- self . add_local_reference ( binding_id, range) ;
274
+ self . add_local_reference ( binding_id, ExprContext :: Del , range) ;
275
275
self . bindings [ binding_id] . is_unbound ( )
276
276
} ) ;
277
277
@@ -296,8 +296,9 @@ impl<'a> SemanticModel<'a> {
296
296
let reference_id = self . resolved_references . push (
297
297
ScopeId :: global ( ) ,
298
298
self . node_id ,
299
- name . range ,
299
+ ExprContext :: Load ,
300
300
self . flags ,
301
+ name. range ,
301
302
) ;
302
303
self . bindings [ binding_id] . references . push ( reference_id) ;
303
304
@@ -308,8 +309,9 @@ impl<'a> SemanticModel<'a> {
308
309
let reference_id = self . resolved_references . push (
309
310
ScopeId :: global ( ) ,
310
311
self . node_id ,
311
- name . range ,
312
+ ExprContext :: Load ,
312
313
self . flags ,
314
+ name. range ,
313
315
) ;
314
316
self . bindings [ binding_id] . references . push ( reference_id) ;
315
317
}
@@ -365,8 +367,9 @@ impl<'a> SemanticModel<'a> {
365
367
let reference_id = self . resolved_references . push (
366
368
self . scope_id ,
367
369
self . node_id ,
368
- name . range ,
370
+ ExprContext :: Load ,
369
371
self . flags ,
372
+ name. range ,
370
373
) ;
371
374
self . bindings [ binding_id] . references . push ( reference_id) ;
372
375
@@ -377,8 +380,9 @@ impl<'a> SemanticModel<'a> {
377
380
let reference_id = self . resolved_references . push (
378
381
self . scope_id ,
379
382
self . node_id ,
380
- name . range ,
383
+ ExprContext :: Load ,
381
384
self . flags ,
385
+ name. range ,
382
386
) ;
383
387
self . bindings [ binding_id] . references . push ( reference_id) ;
384
388
}
@@ -426,6 +430,15 @@ impl<'a> SemanticModel<'a> {
426
430
return ReadResult :: UnboundLocal ( binding_id) ;
427
431
}
428
432
433
+ BindingKind :: ConditionalDeletion ( binding_id) => {
434
+ self . unresolved_references . push (
435
+ name. range ,
436
+ self . exceptions ( ) ,
437
+ UnresolvedReferenceFlags :: empty ( ) ,
438
+ ) ;
439
+ return ReadResult :: UnboundLocal ( binding_id) ;
440
+ }
441
+
429
442
// If we hit an unbound exception that shadowed a bound name, resole to the
430
443
// bound name. For example, given:
431
444
//
@@ -446,8 +459,9 @@ impl<'a> SemanticModel<'a> {
446
459
let reference_id = self . resolved_references . push (
447
460
self . scope_id ,
448
461
self . node_id ,
449
- name . range ,
462
+ ExprContext :: Load ,
450
463
self . flags ,
464
+ name. range ,
451
465
) ;
452
466
self . bindings [ binding_id] . references . push ( reference_id) ;
453
467
@@ -458,8 +472,9 @@ impl<'a> SemanticModel<'a> {
458
472
let reference_id = self . resolved_references . push (
459
473
self . scope_id ,
460
474
self . node_id ,
461
- name . range ,
475
+ ExprContext :: Load ,
462
476
self . flags ,
477
+ name. range ,
463
478
) ;
464
479
self . bindings [ binding_id] . references . push ( reference_id) ;
465
480
}
@@ -548,6 +563,7 @@ impl<'a> SemanticModel<'a> {
548
563
match self . bindings [ binding_id] . kind {
549
564
BindingKind :: Annotation => continue ,
550
565
BindingKind :: Deletion | BindingKind :: UnboundException ( None ) => return None ,
566
+ BindingKind :: ConditionalDeletion ( binding_id) => return Some ( binding_id) ,
551
567
BindingKind :: UnboundException ( Some ( binding_id) ) => return Some ( binding_id) ,
552
568
_ => return Some ( binding_id) ,
553
569
}
@@ -1315,18 +1331,28 @@ impl<'a> SemanticModel<'a> {
1315
1331
}
1316
1332
1317
1333
/// Add a reference to the given [`BindingId`] in the local scope.
1318
- pub fn add_local_reference ( & mut self , binding_id : BindingId , range : TextRange ) {
1334
+ pub fn add_local_reference (
1335
+ & mut self ,
1336
+ binding_id : BindingId ,
1337
+ ctx : ExprContext ,
1338
+ range : TextRange ,
1339
+ ) {
1319
1340
let reference_id =
1320
1341
self . resolved_references
1321
- . push ( self . scope_id , self . node_id , range , self . flags ) ;
1342
+ . push ( self . scope_id , self . node_id , ctx , self . flags , range ) ;
1322
1343
self . bindings [ binding_id] . references . push ( reference_id) ;
1323
1344
}
1324
1345
1325
1346
/// Add a reference to the given [`BindingId`] in the global scope.
1326
- pub fn add_global_reference ( & mut self , binding_id : BindingId , range : TextRange ) {
1347
+ pub fn add_global_reference (
1348
+ & mut self ,
1349
+ binding_id : BindingId ,
1350
+ ctx : ExprContext ,
1351
+ range : TextRange ,
1352
+ ) {
1327
1353
let reference_id =
1328
1354
self . resolved_references
1329
- . push ( ScopeId :: global ( ) , self . node_id , range , self . flags ) ;
1355
+ . push ( ScopeId :: global ( ) , self . node_id , ctx , self . flags , range ) ;
1330
1356
self . bindings [ binding_id] . references . push ( reference_id) ;
1331
1357
}
1332
1358
@@ -1700,7 +1726,6 @@ bitflags! {
1700
1726
/// only required by the Python interpreter, but by runtime type checkers too.
1701
1727
const RUNTIME_REQUIRED_ANNOTATION = 1 << 2 ;
1702
1728
1703
-
1704
1729
/// The model is in a type definition.
1705
1730
///
1706
1731
/// For example, the model could be visiting `int` in:
@@ -1886,7 +1911,6 @@ bitflags! {
1886
1911
/// ```
1887
1912
const COMPREHENSION_ASSIGNMENT = 1 << 19 ;
1888
1913
1889
-
1890
1914
/// The model is in a module / class / function docstring.
1891
1915
///
1892
1916
/// For example, the model could be visiting either the module, class,
0 commit comments