diff --git a/crates/ruff/src/commands/analyze_graph.rs b/crates/ruff/src/commands/analyze_graph.rs index d12d1be232..f040979240 100644 --- a/crates/ruff/src/commands/analyze_graph.rs +++ b/crates/ruff/src/commands/analyze_graph.rs @@ -112,13 +112,13 @@ pub(crate) fn analyze_graph( }; let db = db.snapshot(); + let glob_resolver = glob_resolver.clone(); let root = root.clone(); let result = inner_result.clone(); - let glob_resolver = glob_resolver.clone(); scope.spawn(move |_| { // Identify any imports via static analysis. let mut imports = - ruff_graph::generate(&path, package.as_deref(), string_imports, &db) + ModuleImports::detect(&path, package.as_deref(), string_imports, &db) .unwrap_or_else(|err| { warn!("Failed to generate import map for {path}: {err}"); ModuleImports::default() diff --git a/crates/ruff_graph/src/lib.rs b/crates/ruff_graph/src/lib.rs index e8cb83416d..30989a31cb 100644 --- a/crates/ruff_graph/src/lib.rs +++ b/crates/ruff_graph/src/lib.rs @@ -21,6 +21,39 @@ mod settings; pub struct ModuleImports(BTreeSet); impl ModuleImports { + /// Detect the [`ModuleImports`] for a given Python file. + pub fn detect( + path: &SystemPath, + package: Option<&SystemPath>, + string_imports: bool, + db: &ModuleDb, + ) -> Result { + // Read and parse the source code. + let file = system_path_to_file(db, path)?; + let parsed = parsed_module(db, file); + let module_path = + package.and_then(|package| to_module_path(package.as_std_path(), path.as_std_path())); + let model = SemanticModel::new(db, file); + + // Collect the imports. + let imports = + Collector::new(module_path.as_deref(), string_imports).collect(parsed.syntax()); + + // Resolve the imports. + let mut resolved_imports = ModuleImports::default(); + for import in imports { + let Some(resolved) = Resolver::new(&model).resolve(import) else { + continue; + }; + let Some(path) = resolved.as_system_path() else { + continue; + }; + resolved_imports.insert(path.to_path_buf()); + } + + Ok(resolved_imports) + } + /// Insert a file path into the module imports. pub fn insert(&mut self, path: SystemPathBuf) { self.0.insert(path); @@ -91,35 +124,3 @@ impl FromIterator<(SystemPathBuf, ModuleImports)> for ImportMap { map } } - -/// Generate the module imports for a given Python file. -pub fn generate( - path: &SystemPath, - package: Option<&SystemPath>, - string_imports: bool, - db: &ModuleDb, -) -> Result { - // Read and parse the source code. - let file = system_path_to_file(db, path)?; - let parsed = parsed_module(db, file); - let module_path = - package.and_then(|package| to_module_path(package.as_std_path(), path.as_std_path())); - let model = SemanticModel::new(db, file); - - // Collect the imports. - let imports = Collector::new(module_path.as_deref(), string_imports).collect(parsed.syntax()); - - // Resolve the imports. - let mut resolved_imports = ModuleImports::default(); - for import in imports { - let Some(resolved) = Resolver::new(&model).resolve(import) else { - continue; - }; - let Some(path) = resolved.as_system_path() else { - continue; - }; - resolved_imports.insert(path.to_path_buf()); - } - - Ok(resolved_imports) -}