Initialize a single-project workspace (root `composer.json` exists). This is the standard fast path: read PSR-4 mappings, build the classmap, scan autoload files. Unchanged from the pre-monorepo behaviour except that vendor fields are now collections.
(
&self,
root: &std::path::Path,
php_version: crate::types::PhpVersion,
composer_json: Option<composer::ComposerPackage>,
progress_token: Option<&NumberOrString
| 1448 | /// classmap, scan autoload files. Unchanged from the pre-monorepo |
| 1449 | /// behaviour except that vendor fields are now collections. |
| 1450 | pub(crate) async fn init_single_project( |
| 1451 | &self, |
| 1452 | root: &std::path::Path, |
| 1453 | php_version: crate::types::PhpVersion, |
| 1454 | composer_json: Option<composer::ComposerPackage>, |
| 1455 | progress_token: Option<&NumberOrString>, |
| 1456 | ) { |
| 1457 | if let Some(tok) = progress_token { |
| 1458 | self.progress_report(tok, 10, Some("Reading composer.json".to_string())) |
| 1459 | .await; |
| 1460 | } |
| 1461 | |
| 1462 | let (mappings, vendor_dir) = match &composer_json { |
| 1463 | Some(pkg) => { |
| 1464 | let mappings = composer::extract_psr4_mappings_from_package(pkg); |
| 1465 | let vendor_dir = composer::get_vendor_dir(pkg); |
| 1466 | (mappings, vendor_dir) |
| 1467 | } |
| 1468 | None => (Vec::new(), "vendor".to_string()), |
| 1469 | }; |
| 1470 | |
| 1471 | // Cache the vendor dir path so cross-file scans can skip it |
| 1472 | // without re-reading composer.json on every request. |
| 1473 | let vendor_path = root.join(&vendor_dir); |
| 1474 | self.add_vendor_dir(&vendor_path); |
| 1475 | |
| 1476 | *self.psr4_mappings.write() = mappings; |
| 1477 | |
| 1478 | // ── Build the classmap ────────────────────────────────────── |
| 1479 | let strategy = self.config().indexing.strategy(); |
| 1480 | |
| 1481 | if let Some(tok) = progress_token { |
| 1482 | self.progress_report(tok, 20, Some("Building class index".to_string())) |
| 1483 | .await; |
| 1484 | } |
| 1485 | |
| 1486 | let (classmap, source_label) = match strategy { |
| 1487 | IndexingStrategy::None => { |
| 1488 | let cm = composer::parse_autoload_classmap(root, &vendor_dir); |
| 1489 | (cm, "composer") |
| 1490 | } |
| 1491 | IndexingStrategy::SelfScan | IndexingStrategy::Full => { |
| 1492 | // "self" strategy: scan every PHP file under the |
| 1493 | // workspace root (ignoring .gitignore, hidden dirs, |
| 1494 | // etc.) to discover all classes, functions, and |
| 1495 | // constants — regardless of whether they appear in |
| 1496 | // composer.json's autoload sections. |
| 1497 | // |
| 1498 | // Explicitly skip the vendor directory so it is never |
| 1499 | // walked even when it is not in .gitignore. Vendor |
| 1500 | // packages are scanned separately via installed.json |
| 1501 | // so that third-party classes are still indexed. |
| 1502 | let mut skip_dirs = HashSet::new(); |
| 1503 | skip_dirs.insert(vendor_path.clone()); |
| 1504 | let mut scan = classmap_scanner::scan_workspace_fallback_full(root, &skip_dirs); |
| 1505 | |
| 1506 | // Merge vendor packages (excluded from the workspace |
| 1507 | // walk above, scanned separately here). |
no test coverage detected