| 438 | } |
| 439 | |
| 440 | async fn did_open(&self, params: DidOpenTextDocumentParams) { |
| 441 | let doc = params.text_document; |
| 442 | let uri = doc.uri.to_string(); |
| 443 | let text = Arc::new(doc.text); |
| 444 | |
| 445 | // Track files opened with languageId "blade" so they get |
| 446 | // Blade preprocessing even without a .blade.php extension. |
| 447 | if doc.language_id == "blade" && !crate::blade::is_blade_file(&uri) { |
| 448 | self.blade_uris.write().insert(uri.clone()); |
| 449 | } |
| 450 | |
| 451 | // Store file content |
| 452 | self.open_files |
| 453 | .write() |
| 454 | .insert(uri.clone(), Arc::clone(&text)); |
| 455 | |
| 456 | // Parse and update AST map, use map, and namespace map |
| 457 | self.update_ast(&uri, &text); |
| 458 | |
| 459 | // Schedule diagnostics asynchronously so that the first-open |
| 460 | // response is not blocked by lazy stub parsing (which can take |
| 461 | // tens of seconds when many class references trigger cache-miss |
| 462 | // parses). This matches the did_change path. |
| 463 | self.schedule_diagnostics(uri.clone()); |
| 464 | |
| 465 | self.log(MessageType::INFO, format!("Opened file: {}", uri)) |
| 466 | .await; |
| 467 | } |
| 468 | |
| 469 | async fn did_change(&self, params: DidChangeTextDocumentParams) { |
| 470 | let uri = params.text_document.uri.to_string(); |