Scan a batch of files for all symbols (classes, functions, constants) in parallel and return a [`WorkspaceScanResult`].
(files: &[PathBuf])
| 565 | /// Scan a batch of files for all symbols (classes, functions, constants) |
| 566 | /// in parallel and return a [`WorkspaceScanResult`]. |
| 567 | fn scan_files_parallel_full(files: &[PathBuf]) -> WorkspaceScanResult { |
| 568 | if files.is_empty() { |
| 569 | return WorkspaceScanResult::default(); |
| 570 | } |
| 571 | |
| 572 | // Small batches: sequential |
| 573 | if files.len() <= 4 { |
| 574 | let mut result = WorkspaceScanResult::default(); |
| 575 | for path in files { |
| 576 | if let Ok(content) = std::fs::read(path) { |
| 577 | let scan = find_symbols(&content); |
| 578 | for fqcn in scan.classes { |
| 579 | let class_short_name = fqcn_short_name(&fqcn).to_owned(); |
| 580 | result |
| 581 | .classmap |
| 582 | .entry(fqcn) |
| 583 | .and_modify(|existing| { |
| 584 | let existing_stem = |
| 585 | existing.file_stem().and_then(|s| s.to_str()).unwrap_or(""); |
| 586 | let new_stem = path.file_stem().and_then(|s| s.to_str()).unwrap_or(""); |
| 587 | if existing_stem != class_short_name && new_stem == class_short_name { |
| 588 | *existing = path.clone(); |
| 589 | } |
| 590 | }) |
| 591 | .or_insert_with(|| path.clone()); |
| 592 | } |
| 593 | for fqn in scan.functions { |
| 594 | result |
| 595 | .function_index |
| 596 | .entry(fqn) |
| 597 | .or_insert_with(|| path.clone()); |
| 598 | } |
| 599 | for name in scan.constants { |
| 600 | result |
| 601 | .constant_index |
| 602 | .entry(name) |
| 603 | .or_insert_with(|| path.clone()); |
| 604 | } |
| 605 | } |
| 606 | } |
| 607 | return result; |
| 608 | } |
| 609 | |
| 610 | let n_threads = thread_count().min(files.len()); |
| 611 | let chunk_size = files.len().div_ceil(n_threads); |
| 612 | |
| 613 | let results: Vec<Vec<(ScanResult, PathBuf)>> = std::thread::scope(|s| { |
| 614 | let handles: Vec<_> = files |
| 615 | .chunks(chunk_size) |
| 616 | .map(|chunk| { |
| 617 | s.spawn(move || { |
| 618 | let mut local: Vec<(ScanResult, PathBuf)> = Vec::new(); |
| 619 | for path in chunk { |
| 620 | if let Ok(content) = std::fs::read(path) { |
| 621 | let scan = find_symbols(&content); |
| 622 | if !scan.classes.is_empty() |
| 623 | || !scan.functions.is_empty() |
| 624 | || !scan.constants.is_empty() |
no test coverage detected