@@ -12,7 +12,10 @@ use crate::files::FileId;
12
12
use crate :: symbols:: Dependency ;
13
13
use crate :: FxDashMap ;
14
14
15
- /// ID uniquely identifying a module.
15
+ /// Representation of a Python module.
16
+ ///
17
+ /// The inner type wrapped by this struct is a unique identifier for the module
18
+ /// that is used by the struct's methods to lazily query information about the module.
16
19
#[ derive( Copy , Clone , Debug , Eq , PartialEq , Hash ) ]
17
20
pub struct Module ( u32 ) ;
18
21
@@ -100,7 +103,8 @@ impl Module {
100
103
101
104
/// A module name, e.g. `foo.bar`.
102
105
///
103
- /// Always normalized to the absolute form (never a relative module name).
106
+ /// Always normalized to the absolute form
107
+ /// (never a relative module name, i.e., never `.foo`).
104
108
#[ derive( Clone , Debug , Eq , PartialEq , Hash ) ]
105
109
pub struct ModuleName ( smol_str:: SmolStr ) ;
106
110
@@ -250,9 +254,11 @@ pub struct ModuleData {
250
254
// Queries
251
255
//////////////////////////////////////////////////////
252
256
253
- /// Resolves a module name to a module id
254
- /// TODO: This would not work with Salsa because `ModuleName` isn't an ingredient and, therefore, cannot be used as part of a query.
255
- /// For this to work with salsa, it would be necessary to intern all `ModuleName`s.
257
+ /// Resolves a module name to a module.
258
+ ///
259
+ /// TODO: This would not work with Salsa because `ModuleName` isn't an ingredient
260
+ /// and, therefore, cannot be used as part of a query.
261
+ /// For this to work with salsa, it would be necessary to intern all `ModuleName`s.
256
262
#[ tracing:: instrument( level = "debug" , skip( db) ) ]
257
263
pub fn resolve_module ( db : & dyn SemanticDb , name : ModuleName ) -> QueryResult < Option < Module > > {
258
264
let jar: & SemanticJar = db. jar ( ) ?;
@@ -274,15 +280,15 @@ pub fn resolve_module(db: &dyn SemanticDb, name: ModuleName) -> QueryResult<Opti
274
280
let file_id = db. file_id ( & normalized) ;
275
281
let path = ModulePath :: new ( root_path. clone ( ) , file_id) ;
276
282
277
- let id = Module (
283
+ let module = Module (
278
284
modules
279
285
. next_module_id
280
286
. fetch_add ( 1 , std:: sync:: atomic:: Ordering :: Relaxed ) ,
281
287
) ;
282
288
283
289
modules
284
290
. modules
285
- . insert ( id , Arc :: from ( ModuleData { name, path, kind } ) ) ;
291
+ . insert ( module , Arc :: from ( ModuleData { name, path, kind } ) ) ;
286
292
287
293
// A path can map to multiple modules because of symlinks:
288
294
// ```
@@ -291,33 +297,33 @@ pub fn resolve_module(db: &dyn SemanticDb, name: ModuleName) -> QueryResult<Opti
291
297
// ```
292
298
// Here, both `foo` and `bar` resolve to the same module but through different paths.
293
299
// That's why we need to insert the absolute path and not the normalized path here.
294
- let absolute_id = if absolute_path == normalized {
300
+ let absolute_file_id = if absolute_path == normalized {
295
301
file_id
296
302
} else {
297
303
db. file_id ( & absolute_path)
298
304
} ;
299
305
300
- modules. by_file . insert ( absolute_id , id ) ;
306
+ modules. by_file . insert ( absolute_file_id , module ) ;
301
307
302
- entry. insert_entry ( id ) ;
308
+ entry. insert_entry ( module ) ;
303
309
304
- Ok ( Some ( id ) )
310
+ Ok ( Some ( module ) )
305
311
}
306
312
}
307
313
}
308
314
309
- /// Resolves the module id for the given path.
315
+ /// Resolves the module for the given path.
310
316
///
311
- /// Returns `None` if the path is not a module in `sys.path`.
317
+ /// Returns `None` if the path is not a module locatable via `sys.path`.
312
318
#[ tracing:: instrument( level = "debug" , skip( db) ) ]
313
319
pub fn path_to_module ( db : & dyn SemanticDb , path : & Path ) -> QueryResult < Option < Module > > {
314
320
let file = db. file_id ( path) ;
315
321
file_to_module ( db, file)
316
322
}
317
323
318
- /// Resolves the module id for the file with the given id.
324
+ /// Resolves the module for the file with the given id.
319
325
///
320
- /// Returns `None` if the file is not a module in `sys.path`.
326
+ /// Returns `None` if the file is not a module locatable via `sys.path`.
321
327
#[ tracing:: instrument( level = "debug" , skip( db) ) ]
322
328
pub fn file_to_module ( db : & dyn SemanticDb , file : FileId ) -> QueryResult < Option < Module > > {
323
329
let jar: & SemanticJar = db. jar ( ) ?;
@@ -344,12 +350,12 @@ pub fn file_to_module(db: &dyn SemanticDb, file: FileId) -> QueryResult<Option<M
344
350
345
351
// Resolve the module name to see if Python would resolve the name to the same path.
346
352
// If it doesn't, then that means that multiple modules have the same in different
347
- // root paths, but that the module corresponding to the past path is in a lower priority path,
353
+ // root paths, but that the module corresponding to the past path is in a lower priority search path,
348
354
// in which case we ignore it.
349
- let Some ( module_id ) = resolve_module ( db, module_name) ? else {
355
+ let Some ( module ) = resolve_module ( db, module_name) ? else {
350
356
return Ok ( None ) ;
351
357
} ;
352
- let module_path = module_id . path ( db) ?;
358
+ let module_path = module . path ( db) ?;
353
359
354
360
if module_path. root ( ) == & root_path {
355
361
let Ok ( normalized) = path. canonicalize ( ) else {
@@ -369,7 +375,7 @@ pub fn file_to_module(db: &dyn SemanticDb, file: FileId) -> QueryResult<Option<M
369
375
}
370
376
371
377
// Path has been inserted by `resolved`
372
- Ok ( Some ( module_id ) )
378
+ Ok ( Some ( module ) )
373
379
} else {
374
380
// This path is for a module with the same name but in a module search path with a lower priority.
375
381
// Ignore it.
@@ -388,19 +394,22 @@ pub fn set_module_search_paths(db: &mut dyn SemanticDb, search_paths: Vec<Module
388
394
jar. module_resolver = ModuleResolver :: new ( search_paths) ;
389
395
}
390
396
391
- /// Adds a module to the resolver.
397
+ /// Adds a module located at `path` to the resolver.
392
398
///
393
399
/// Returns `None` if the path doesn't resolve to a module.
394
400
///
395
- /// Returns `Some` with the id of the module and the ids of the modules that need re-resolving
396
- /// because they were part of a namespace package and might now resolve differently.
401
+ /// Returns `Some(module, other_modules)`, where `module` is the resolved module
402
+ /// with file location `path`, and `other_modules` is a `Vec` of `ModuleData` instances.
403
+ /// Each element in `other_modules` provides information regarding a single module that needs
404
+ /// re-resolving because it was part of a namespace package and might now resolve differently.
405
+ ///
397
406
/// Note: This won't work with salsa because `Path` is not an ingredient.
398
407
pub fn add_module ( db : & mut dyn SemanticDb , path : & Path ) -> Option < ( Module , Vec < Arc < ModuleData > > ) > {
399
408
// No locking is required because we're holding a mutable reference to `modules`.
400
409
401
410
// TODO This needs tests
402
411
403
- // Note: Intentionally by-pass caching here. Module should not be in the cache yet.
412
+ // Note: Intentionally bypass caching here. Module should not be in the cache yet.
404
413
let module = path_to_module ( db, path) . ok ( ) ??;
405
414
406
415
// The code below is to handle the addition of `__init__.py` files.
@@ -424,15 +433,15 @@ pub fn add_module(db: &mut dyn SemanticDb, path: &Path) -> Option<(Module, Vec<A
424
433
let jar: & mut SemanticJar = db. jar_mut ( ) ;
425
434
let modules = & mut jar. module_resolver ;
426
435
427
- modules. by_file . retain ( |_, id | {
436
+ modules. by_file . retain ( |_, module | {
428
437
if modules
429
438
. modules
430
- . get ( id )
439
+ . get ( module )
431
440
. unwrap ( )
432
441
. name
433
442
. starts_with ( & parent_name)
434
443
{
435
- to_remove. push ( * id ) ;
444
+ to_remove. push ( * module ) ;
436
445
false
437
446
} else {
438
447
true
@@ -441,8 +450,8 @@ pub fn add_module(db: &mut dyn SemanticDb, path: &Path) -> Option<(Module, Vec<A
441
450
442
451
// TODO remove need for this vec
443
452
let mut removed = Vec :: with_capacity ( to_remove. len ( ) ) ;
444
- for id in & to_remove {
445
- removed. push ( modules. remove_module_by_id ( * id ) ) ;
453
+ for module in & to_remove {
454
+ removed. push ( modules. remove_module ( * module ) ) ;
446
455
}
447
456
448
457
Some ( ( module, removed) )
@@ -455,10 +464,10 @@ pub struct ModuleResolver {
455
464
456
465
// Locking: Locking is done by acquiring a (write) lock on `by_name`. This is because `by_name` is the primary
457
466
// lookup method. Acquiring locks in any other ordering can result in deadlocks.
458
- /// Resolves a module name to it's module id.
467
+ /// Looks up a module by name
459
468
by_name : FxDashMap < ModuleName , Module > ,
460
469
461
- /// All known modules, indexed by the module id.
470
+ /// A map of all known modules to data about those modules
462
471
modules : FxDashMap < Module , Arc < ModuleData > > ,
463
472
464
473
/// Lookup from absolute path to module.
@@ -479,24 +488,26 @@ impl ModuleResolver {
479
488
}
480
489
481
490
/// Remove a module from the inner cache
482
- pub ( crate ) fn remove_module ( & mut self , file_id : FileId ) {
491
+ pub ( crate ) fn remove_module_by_file ( & mut self , file_id : FileId ) {
483
492
// No locking is required because we're holding a mutable reference to `self`.
484
- let Some ( ( _, id ) ) = self . by_file . remove ( & file_id) else {
493
+ let Some ( ( _, module ) ) = self . by_file . remove ( & file_id) else {
485
494
return ;
486
495
} ;
487
496
488
- self . remove_module_by_id ( id ) ;
497
+ self . remove_module ( module ) ;
489
498
}
490
499
491
- fn remove_module_by_id ( & mut self , id : Module ) -> Arc < ModuleData > {
492
- let ( _, module ) = self . modules . remove ( & id ) . unwrap ( ) ;
500
+ fn remove_module ( & mut self , module : Module ) -> Arc < ModuleData > {
501
+ let ( _, module_data ) = self . modules . remove ( & module ) . unwrap ( ) ;
493
502
494
- self . by_name . remove ( & module . name ) . unwrap ( ) ;
503
+ self . by_name . remove ( & module_data . name ) . unwrap ( ) ;
495
504
496
- // It's possible that multiple paths map to the same id. Search all other paths referencing the same module id.
497
- self . by_file . retain ( |_, current_id| * current_id != id) ;
505
+ // It's possible that multiple paths map to the same module.
506
+ // Search all other paths referencing the same module.
507
+ self . by_file
508
+ . retain ( |_, current_module| * current_module != module) ;
498
509
499
- module
510
+ module_data
500
511
}
501
512
}
502
513
0 commit comments