Skip to content

Commit 4f285fb

Browse files
committed
Fix massive startup delay (waiting for full dianostics)
1 parent 5c2caab commit 4f285fb

3 files changed

Lines changed: 11 additions & 5 deletions

File tree

docs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3737
- **Inherited `@method` and `@property` tags.** Virtual members declared via `@method` or `@property` on a parent class now appear on child classes. Previously only the declaring class itself surfaced these members.
3838
- **Class constant and enum case assignment resolution.** Assigning from a class constant (`$x = Foo::SOME_CONST`) or enum case (`$x = Status::Active`) now resolves the variable's type correctly for subsequent completion.
3939
- **Sequential assert narrowing.** Multiple `assert($x instanceof A); assert($x instanceof B);` statements now accumulate, showing members from both types. Previously only the last assertion's narrowing applied.
40+
- **First-open performance.** Diagnostics on `did_open` now run asynchronously (matching `did_change` behaviour) instead of blocking the LSP response. Previously, opening a file with many class references triggered a cascade of lazy stub and vendor file parses that froze the editor for up to 20 seconds.
4041
- **`instanceof` narrowing no longer widens specific types.** `assert($zoo instanceof ZooBase)` after `$zoo = new Zoo()` (where `Zoo extends ZooBase`) no longer replaces the type with the less-specific parent. The narrower `Zoo` type is preserved because it already satisfies the check. Previously this produced false-positive "unknown member" warnings for `@property` and `@method` members declared on the child class.
4142
- **Arrow function parameter completion with incomplete expressions.** Typing `$foo->` inside an arrow function body (e.g. `fn(Foo $foo) => $foo->`) now resolves the parameter type even when the expression is incomplete. The parser recovery inserts a dummy token so the surrounding arrow function structure is recognized.
4243
- **False-positive unknown-class warnings on PHPStan type syntax.** String literals in conditional return types (`$param is "foo" ? A : B`), numeric literals, and variance annotations on generic arguments (`Collection<int, covariant array{...}>`) no longer trigger "Class not found" warnings.

src/diagnostics/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,11 @@ const DIAGNOSTIC_DEBOUNCE_MS: u64 = 500;
5050
impl Backend {
5151
/// Collect all diagnostics for a single file and publish them.
5252
///
53-
/// Called from `did_open` (synchronously, since the user expects to
54-
/// see issues on first open) and from the diagnostic worker task
55-
/// spawned by [`schedule_diagnostics`](Self::schedule_diagnostics).
53+
/// Called from the diagnostic worker task spawned by
54+
/// [`schedule_diagnostics`](Self::schedule_diagnostics). Both
55+
/// `did_open` and `did_change` schedule diagnostics asynchronously
56+
/// so that lazy stub parsing (which can trigger hundreds of
57+
/// cache-miss parses on first open) never blocks the LSP response.
5658
///
5759
/// `uri_str` is the file URI string (e.g. `"file:///path/to/file.php"`).
5860
/// `content` is the full text of the file.

src/server.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,11 @@ impl LanguageServer for Backend {
265265
// Parse and update AST map, use map, and namespace map
266266
self.update_ast(&uri, &text);
267267

268-
// Publish diagnostics (deprecated usage, unused imports, etc.)
269-
self.publish_diagnostics_for_file(&uri, &text).await;
268+
// Schedule diagnostics asynchronously so that the first-open
269+
// response is not blocked by lazy stub parsing (which can take
270+
// tens of seconds when many class references trigger cache-miss
271+
// parses). This matches the did_change path.
272+
self.schedule_diagnostics(uri.clone());
270273

271274
self.log(MessageType::INFO, format!("Opened file: {}", uri))
272275
.await;

0 commit comments

Comments
 (0)