Scan a batch of files for class names with PSR-4 filtering in parallel. Each entry is `(file_path, expected_fqn)`. Only classes whose FQN matches the expected FQN are included.
(files: &[(PathBuf, String)])
| 500 | /// Each entry is `(file_path, expected_fqn)`. Only classes whose FQN |
| 501 | /// matches the expected FQN are included. |
| 502 | fn scan_files_parallel_psr4(files: &[(PathBuf, String)]) -> HashMap<String, PathBuf> { |
| 503 | if files.is_empty() { |
| 504 | return HashMap::new(); |
| 505 | } |
| 506 | |
| 507 | // Small batches: sequential |
| 508 | if files.len() <= 4 { |
| 509 | let mut classmap = HashMap::new(); |
| 510 | for (path, expected_fqn) in files { |
| 511 | if let Ok(content) = std::fs::read(path) { |
| 512 | for fqcn in scan_content(&content) { |
| 513 | if &fqcn == expected_fqn { |
| 514 | classmap.entry(fqcn).or_insert_with(|| path.clone()); |
| 515 | } |
| 516 | } |
| 517 | } |
| 518 | } |
| 519 | return classmap; |
| 520 | } |
| 521 | |
| 522 | let n_threads = thread_count().min(files.len()); |
| 523 | let chunk_size = files.len().div_ceil(n_threads); |
| 524 | |
| 525 | let results: Vec<Vec<(String, PathBuf)>> = std::thread::scope(|s| { |
| 526 | let handles: Vec<_> = files |
| 527 | .chunks(chunk_size) |
| 528 | .map(|chunk| { |
| 529 | s.spawn(move || { |
| 530 | let mut local: Vec<(String, PathBuf)> = Vec::new(); |
| 531 | for (path, expected_fqn) in chunk { |
| 532 | if let Ok(content) = std::fs::read(path) { |
| 533 | for fqcn in scan_content(&content) { |
| 534 | if &fqcn == expected_fqn { |
| 535 | local.push((fqcn, path.clone())); |
| 536 | } |
| 537 | } |
| 538 | } |
| 539 | } |
| 540 | local |
| 541 | }) |
| 542 | }) |
| 543 | .collect(); |
| 544 | handles |
| 545 | .into_iter() |
| 546 | .map(|h| { |
| 547 | h.join().unwrap_or_else(|_| { |
| 548 | tracing::error!("PHPantom: thread panic in scan_files_parallel_psr4"); |
| 549 | Vec::new() |
| 550 | }) |
| 551 | }) |
| 552 | .collect() |
| 553 | }); |
| 554 | |
| 555 | let total: usize = results.iter().map(|v| v.len()).sum(); |
| 556 | let mut classmap = HashMap::with_capacity(total); |
| 557 | for batch in results { |
| 558 | for (fqcn, path) in batch { |
| 559 | classmap.entry(fqcn).or_insert(path); |
no test coverage detected