diff --git a/crates/ty_python_semantic/src/module_resolver/resolver.rs b/crates/ty_python_semantic/src/module_resolver/resolver.rs index 8938814798..901b4f44f1 100644 --- a/crates/ty_python_semantic/src/module_resolver/resolver.rs +++ b/crates/ty_python_semantic/src/module_resolver/resolver.rs @@ -334,7 +334,7 @@ pub(crate) fn file_to_module(db: &dyn Db, file: File) -> Option> { db, file, path, - desperate_search_paths(db, file).iter().flatten(), + simple_desperate_search_paths(db, file).iter(), ) }) } @@ -449,10 +449,64 @@ fn desperate_search_paths(db: &dyn Db, importing_file: File) -> Option Option { + let system = db.system(); + let importing_path = importing_file.path(db).as_system_path()?; + + // Only allow this if the importing_file is under the first-party search path + let (base_path, rel_path) = + search_paths(db, ModuleResolveMode::StubsAllowed).find_map(|search_path| { + if !search_path.is_first_party() { + return None; + } + Some(( + search_path.as_system_path()?, + search_path.relativize_system_path_only(importing_path)?, + )) + })?; + + // Read the revision on the corresponding file root to + // register an explicit dependency on this directory. When + // the revision gets bumped, the cache that Salsa creates + // for this routine will be invalidated. + // + // (This is conditional because ruff uses this code too and doesn't set roots) + if let Some(root) = db.files().root(db, base_path) { + let _ = root.revision(db); + } + + // Only allow searching up to the first-party path's root + for rel_dir in rel_path.ancestors() { + let candidate_path = base_path.join(rel_dir); + // Any dir with a pyproject.toml or ty.toml might be a project root + if system.is_file(&candidate_path.join("pyproject.toml")) + || system.is_file(&candidate_path.join("ty.toml")) + { + let search_path = SearchPath::first_party(system, candidate_path).ok()?; + return Some(search_path); + } + } + + None +} #[derive(Clone, Debug, PartialEq, Eq, get_size2::GetSize)] pub struct SearchPaths { /// Search paths that have been statically determined purely from reading