11use ruff_db:: files:: FilePath ;
2- use ty_python_semantic:: resolve_module;
2+ use ty_python_semantic:: { ModuleName , resolve_module, resolve_real_module } ;
33
44use crate :: ModuleDb ;
55use crate :: collector:: CollectedImport ;
@@ -16,24 +16,67 @@ impl<'a> Resolver<'a> {
1616 }
1717
1818 /// Resolve the [`CollectedImport`] into a [`FilePath`].
19- pub ( crate ) fn resolve ( & self , import : CollectedImport ) -> Option < & ' a FilePath > {
19+ pub ( crate ) fn resolve ( & self , import : CollectedImport ) -> impl Iterator < Item = & ' a FilePath > {
2020 match import {
2121 CollectedImport :: Import ( import) => {
22- let module = resolve_module ( self . db , & import) ?;
23- Some ( module. file ( self . db ) ?. path ( self . db ) )
22+ // Attempt to resolve the module (e.g., given `import foo`, look for `foo`).
23+ let file = self . resolve_module ( & import) ;
24+
25+ // If the file is a stub, look for the corresponding source file.
26+ let source_file = file
27+ . is_some_and ( |file| file. extension ( ) == Some ( "pyi" ) )
28+ . then ( || self . resolve_real_module ( & import) )
29+ . flatten ( ) ;
30+
31+ std:: iter:: once ( file)
32+ . chain ( std:: iter:: once ( source_file) )
33+ . flatten ( )
2434 }
2535 CollectedImport :: ImportFrom ( import) => {
2636 // Attempt to resolve the member (e.g., given `from foo import bar`, look for `foo.bar`).
27- let parent = import. parent ( ) ;
37+ if let Some ( file) = self . resolve_module ( & import) {
38+ // If the file is a stub, look for the corresponding source file.
39+ let source_file = ( file. extension ( ) == Some ( "pyi" ) )
40+ . then ( || self . resolve_real_module ( & import) )
41+ . flatten ( ) ;
2842
29- let module = resolve_module ( self . db , & import) . or_else ( || {
30- // Attempt to resolve the module (e.g., given `from foo import bar`, look for `foo`).
43+ return std:: iter:: once ( Some ( file) )
44+ . chain ( std:: iter:: once ( source_file) )
45+ . flatten ( ) ;
46+ }
47+
48+ // Attempt to resolve the module (e.g., given `from foo import bar`, look for `foo`).
49+ let parent = import. parent ( ) ;
50+ let file = parent
51+ . as_ref ( )
52+ . and_then ( |parent| self . resolve_module ( parent) ) ;
3153
32- resolve_module ( self . db , & parent?)
33- } ) ?;
54+ // If the file is a stub, look for the corresponding source file.
55+ let source_file = file
56+ . is_some_and ( |file| file. extension ( ) == Some ( "pyi" ) )
57+ . then ( || {
58+ parent
59+ . as_ref ( )
60+ . and_then ( |parent| self . resolve_real_module ( parent) )
61+ } )
62+ . flatten ( ) ;
3463
35- Some ( module. file ( self . db ) ?. path ( self . db ) )
64+ std:: iter:: once ( file)
65+ . chain ( std:: iter:: once ( source_file) )
66+ . flatten ( )
3667 }
3768 }
3869 }
70+
71+ /// Resolves a module name to a module.
72+ fn resolve_module ( & self , module_name : & ModuleName ) -> Option < & ' a FilePath > {
73+ let module = resolve_module ( self . db , module_name) ?;
74+ Some ( module. file ( self . db ) ?. path ( self . db ) )
75+ }
76+
77+ /// Resolves a module name to a module (stubs not allowed).
78+ fn resolve_real_module ( & self , module_name : & ModuleName ) -> Option < & ' a FilePath > {
79+ let module = resolve_real_module ( self . db , module_name) ?;
80+ Some ( module. file ( self . db ) ?. path ( self . db ) )
81+ }
3982}
0 commit comments