Scan autoload files for a single project root and populate the autoload indices. Returns the number of autoload file entries found.
(
&self,
project_root: &std::path::Path,
vendor_dir: &str,
)
| 1863 | /// autoload indices. Returns the number of autoload file entries |
| 1864 | /// found. |
| 1865 | pub(crate) fn scan_autoload_files( |
| 1866 | &self, |
| 1867 | project_root: &std::path::Path, |
| 1868 | vendor_dir: &str, |
| 1869 | ) -> usize { |
| 1870 | let autoload_files = composer::parse_autoload_files(project_root, vendor_dir); |
| 1871 | let autoload_count = autoload_files.len(); |
| 1872 | |
| 1873 | // Work queue + visited set for following require_once chains. |
| 1874 | let mut file_queue: Vec<PathBuf> = autoload_files; |
| 1875 | let mut visited: HashSet<PathBuf> = HashSet::new(); |
| 1876 | |
| 1877 | while let Some(file_path) = file_queue.pop() { |
| 1878 | // Canonicalise to avoid revisiting the same file via |
| 1879 | // different relative paths. |
| 1880 | let canonical = file_path.canonicalize().unwrap_or(file_path); |
| 1881 | if !visited.insert(canonical.clone()) { |
| 1882 | continue; |
| 1883 | } |
| 1884 | |
| 1885 | if let Ok(content) = std::fs::read(&canonical) { |
| 1886 | let uri = crate::util::path_to_uri(&canonical); |
| 1887 | |
| 1888 | // Lightweight byte-level scan: extract symbol names |
| 1889 | // without building a full AST. |
| 1890 | let scan = classmap_scanner::find_symbols(&content); |
| 1891 | |
| 1892 | // Populate function index. |
| 1893 | { |
| 1894 | let mut idx = self.autoload_function_index.write(); |
| 1895 | for fqn in &scan.functions { |
| 1896 | idx.entry(fqn.clone()).or_insert_with(|| canonical.clone()); |
| 1897 | } |
| 1898 | } |
| 1899 | |
| 1900 | // Populate constant index. |
| 1901 | { |
| 1902 | let mut idx = self.autoload_constant_index.write(); |
| 1903 | for name in &scan.constants { |
| 1904 | idx.entry(name.clone()).or_insert_with(|| canonical.clone()); |
| 1905 | } |
| 1906 | } |
| 1907 | |
| 1908 | // Populate fqn_uri_index so find_or_load_class can |
| 1909 | // lazily parse these classes later. |
| 1910 | { |
| 1911 | let mut idx = self.fqn_uri_index.write(); |
| 1912 | for fqn in &scan.classes { |
| 1913 | idx.entry(fqn.clone()).or_insert_with(|| uri.clone()); |
| 1914 | } |
| 1915 | } |
| 1916 | |
| 1917 | let content_str = String::from_utf8_lossy(&content); |
| 1918 | |
| 1919 | // ── Phar detection ────────────────────────────────── |
| 1920 | // If this autoload file references a .phar archive, |
| 1921 | // parse the phar and scan its PHP files for classes. |
| 1922 | if let Some(file_dir) = canonical.parent() { |
no test coverage detected