| 223 | } |
| 224 | |
| 225 | async fn initialized(&self, _: InitializedParams) { |
| 226 | // Parse composer.json for PSR-4 mappings if we have a workspace root |
| 227 | let workspace_root = self.workspace_root.read().clone(); |
| 228 | |
| 229 | if let Some(root) = workspace_root { |
| 230 | // ── Load project configuration ────────────────────────────── |
| 231 | // Read `.phpantom.toml` before anything else so that settings |
| 232 | // (e.g. PHP version override, diagnostic toggles) are active |
| 233 | // from the very first file load. |
| 234 | match crate::config::load_config(&root) { |
| 235 | Ok(cfg) => { |
| 236 | *self.config.lock() = cfg; |
| 237 | } |
| 238 | Err(e) => { |
| 239 | self.log( |
| 240 | MessageType::WARNING, |
| 241 | format!("Failed to load .phpantom.toml: {}", e), |
| 242 | ) |
| 243 | .await; |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | // Parse composer.json once up front. The result is used for |
| 248 | // PHP version detection and passed into init_single_project |
| 249 | // so the file is never re-read during startup. |
| 250 | let composer_package = composer::read_composer_package(&root); |
| 251 | |
| 252 | // Detect the target PHP version. The config file override |
| 253 | // takes precedence; otherwise fall back to composer.json. |
| 254 | let php_version = self |
| 255 | .config() |
| 256 | .php |
| 257 | .version |
| 258 | .as_deref() |
| 259 | .and_then(crate::types::PhpVersion::from_composer_constraint) |
| 260 | .unwrap_or_else(|| { |
| 261 | composer_package |
| 262 | .as_ref() |
| 263 | .and_then(composer::detect_php_version_from_package) |
| 264 | .unwrap_or_default() |
| 265 | }); |
| 266 | self.set_php_version(php_version); |
| 267 | |
| 268 | let has_composer_json = composer_package.is_some(); |
| 269 | |
| 270 | // ── Create a progress token for indexing feedback ──────── |
| 271 | let progress_token = self.progress_create("phpantom/indexing").await; |
| 272 | if let Some(ref tok) = progress_token { |
| 273 | self.progress_begin(tok, "PHPantom: Indexing", Some("Starting".to_string())) |
| 274 | .await; |
| 275 | } |
| 276 | |
| 277 | if has_composer_json { |
| 278 | // ── Single-project path (root composer.json exists) ────── |
| 279 | self.init_single_project( |
| 280 | &root, |
| 281 | php_version, |
| 282 | composer_package, |