You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/CHANGELOG.md
+4-2Lines changed: 4 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -23,7 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
23
23
-**Closure and arrow function inlay hints.** When a closure or arrow function is passed to a callable-typed parameter, inlay hints show inferred parameter types and the return type. Types are derived from the enclosing callable signature with generic substitution from sibling arguments.
24
24
-**Return type inference from method bodies.** Methods without a declared return type or `@return` docblock now have their return type inferred from `return` statements, improving completion, hover, and diagnostics for untyped code.
25
25
-**Untyped property type inference from constructor.** Properties without type declarations are resolved by inspecting the constructor body for assignments and promoted parameter defaults. PHPDoc generation uses the inferred type. Contributed by @lucasacoutinho in https://github.com/AJenbo/phpantom_lsp/pull/81.
26
-
-**Binary expression type inference.** Hover and variable resolution now show result types for all binary operators: arithmetic (`int|float`), concatenation (`string`), comparison and logical (`bool`), bitwise (`int`), and `+` distinguishes array union from numeric addition based on operand types.
26
+
-**Binary expression type inference.** Hover and variable resolution now show result types for all binary operators with operand-type-aware arithmetic (`int + int` → `int`, `int + float` → `float`, `int / int` → `int|float`). Concatenation returns `string`, comparison and logical return `bool`, bitwise returns `int` (or `string` when both operands are strings), spaceship returns `int`, and `+` distinguishes array union from numeric addition. Compound assignments (`/=`, `*=`, `%=`, `**=`, `.=`, `<<=`, `&=`, `|=`, `^=`, `??=`) update the variable's type with the same operand-aware rules. Incrementing a numeric string literal (`$a = "123"; $a++`) produces `int|float`. Parenthesized binary expressions resolve correctly through the structural inference path.
27
27
-**`array_reduce`, `array_sum`, and `array_product` return type inference.**`array_reduce()` resolves to the type of its initial value argument. `array_sum()` and `array_product()` resolve to `int|float`.
28
28
-**`global` keyword variable resolution.** Variables imported with `global $var` now resolve to their top-level type, enabling completion, hover, and go-to-definition.
29
29
-**Nested array shape inference from multi-level key assignments.** Assignments like `$b['a']['b'] = 'x'` now produce a nested array shape type (`array{a: array{b: string}}`), enabling array key completion for arrays built incrementally with nested keys.
@@ -33,9 +33,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
33
33
34
34
### Fixed
35
35
36
-
-**`isset()` narrowing.**`isset($x)` in a condition now strips `null` from the variable's type in the truthy branch (matching `$x !== null` semantics). `!isset($x)` narrows to `null` only. Both simple variables and property access (`$obj->prop`) are supported, and multiple arguments (`isset($a, $b)`) narrow all listed variables. Guard clauses (`if (!isset($x)) { return; }`) strip null from the variable in the code that follows.
36
+
-**First-class callable invocation return types.** Immediately invoking a first-class callable (`Foo::method(...)()`, `$this->method(...)()`, `self::method(...)()`, `static::method(...)()`, `parent::method(...)()`, `func(...)()`) now resolves to the underlying method or function's return type. Previously these expressions returned no type.
37
+
-**`isset()` and `empty()` narrowing.**`isset($x)` in a condition now strips `null` from the variable's type in the truthy branch (matching `$x !== null` semantics). `!isset($x)` narrows to `null` only. `!empty($x)` strips `null` from nullable types (e.g. `string|null` narrows to `string`). Both simple variables and property access (`$obj->prop`) are supported, and multiple arguments (`isset($a, $b)`) narrow all listed variables. Guard clauses (`if (!isset($x)) { return; }`) strip null from the variable in the code that follows.
37
38
-**Hover scales linearly on large files.** Processing many hover requests on the same file (e.g. a test suite with 80+ assertion calls) no longer takes O(n²) time. The first hover on a method body walks it once and caches scope snapshots; every subsequent hover on the same file content is an O(log n) lookup with no re-walk.
38
39
40
+
-**`@return numeric` pseudo-type.** Functions annotated with `@return numeric` now resolve to the `numeric` pseudo-type instead of `string`. Arithmetic on `numeric` operands correctly infers `int|float`, and `$a++` on a `numeric` variable yields `int|float`. The underlying cause was that same-file function calls in multi-namespace files fell through to an incorrect fallback when the file-level namespace differed from the function's namespace.
39
41
-**`parent::__construct()` with `@extends` generics.** Calling `parent::__construct($arg)` in a child class that specifies `@extends Parent<Concrete>` no longer produces false-positive type errors for the substituted parameter types.
40
42
-**Array access on bare `array` and `mixed` types.** Accessing a key on a parameter typed as plain `array` (e.g. `$params['key']`) now resolves to `mixed` instead of an empty type, eliminating false-positive type errors downstream (e.g. `$x = $params['key'] ?? null` followed by an `is_string()` guard).
41
43
-**Analyzer and LSP no longer hang on files with deeply nested loops.** Files with multiple levels of foreach/while/for inside if-branches no longer cause exponential blowup.
0 commit comments