Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- **Return type mismatch diagnostics (`type_mismatch_return`).** Functions and methods with a declared return type are now checked against their `return` statements. Incompatible return values are flagged as errors. Void functions returning a value and bare `return;` in non-void functions are also flagged. Generators (functions using `yield`) are skipped. Uses the same conservative `is_type_compatible` policy as argument type checking to avoid false positives. Contributed by @calebdw.
- **Property type assignment diagnostics (`type_mismatch_property`).** Assignments to typed properties (`$this->prop = expr` and `self::$prop = expr`) are checked against the declared property type. Incompatible values are flagged as errors. Only plain `=` assignments are checked; compound operators (`+=`, `.=`, etc.) are skipped. Untyped and `mixed` properties are not flagged. Contributed by @calebdw.
- **Completion candidates ranked by dependency provenance.** Class, function, and constant completions are now sorted by origin tier: project code first, then core/stub symbols, then explicit Composer dependencies (`require` / `require-dev`), then transitive vendor dependencies last. The provenance is inferred from `composer.json` and `installed.json` during indexing. Contributed by @calebdw.
- **`update` command.** A new `phpantom_lsp update` subcommand downloads the latest release from GitHub and replaces the current binary. Supports `--check` (dry run, exit code 1 if update available) and `--no-confirm` (for CI). Handles `.tar.gz` (Unix) and `.zip` (Windows) archives across all 6 supported platforms. Contributed by @calebdw in https://github.com/PHPantom-dev/phpantom_lsp/pull/194.
- **`array_map` infers the output element type from its callback.** The result of `array_map` now reflects what the callback actually returns instead of assuming the input element type is preserved. An explicit return type hint is honoured, including scalars like `string` or `int`, so `array_map(fn(Item $item): string => $item->id, $items)` produces `list<string>` rather than `list<Item>`. When the callback has no return type hint, the type is inferred from its body expression, so `array_map(fn($item) => $item->id, $items)` over a `list<Item>` also produces `list<string>`. Fixes #147. (contributed by @calebdw in https://github.com/PHPantom-dev/phpantom_lsp/pull/195)
Expand Down
8 changes: 7 additions & 1 deletion src/analyse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,13 @@ pub async fn run(options: AnalyseOptions) -> i32 {
b.collect_argument_count_diagnostics(u, c, o)
}),
("type_mismatch_argument", &|b, u, c, o| {
b.collect_type_error_diagnostics(u, c, o)
b.collect_argument_type_diagnostics(u, c, o)
}),
("type_mismatch_return", &|b, u, c, o| {
b.collect_return_type_diagnostics(u, c, o)
}),
("type_mismatch_property", &|b, u, c, o| {
b.collect_property_type_diagnostics(u, c, o)
}),
("missing_implementation", &|b, u, c, o| {
b.collect_implementation_error_diagnostics(u, c, o)
Expand Down
25 changes: 23 additions & 2 deletions src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
//! 3. **`unknown_*`** — symbol could not be resolved (class, function,
//! member, variable).
//! 4. **`unused_*`** — symbol is defined/imported but never referenced.
//! 5. **`type_mismatch_*`** — a value's type doesn't satisfy a constraint.
//! 5. **`type_mismatch_*`** — a value's type doesn't satisfy a constraint
//! (`type_mismatch_argument`, `type_mismatch_return`,
//! `type_mismatch_property`).
//! 6. **`missing_*`** — a required declaration is absent (e.g.
//! `missing_implementation` for unimplemented interface methods).
//! 7. **`invalid_*`** — a structural/syntactic violation (e.g.
Expand Down Expand Up @@ -165,6 +167,8 @@ mod deprecated;
pub(crate) mod helpers;
mod implementation_errors;
mod invalid_class_kind;
mod property_type_errors;
mod return_type_errors;
mod syntax_errors;
mod type_errors;
pub(crate) mod undefined_variables;
Expand Down Expand Up @@ -272,12 +276,29 @@ impl Backend {
// inside collect_unknown_member_diagnostics (in the Untyped arm)
// to avoid a second full walk with duplicate type resolution.
self.collect_argument_count_diagnostics(uri_str, content, out);
self.collect_type_error_diagnostics(uri_str, content, out);
self.collect_type_mismatch_diagnostics(uri_str, content, out);
self.collect_implementation_error_diagnostics(uri_str, content, out);
self.collect_deprecated_diagnostics(uri_str, content, out);
self.collect_undefined_variable_diagnostics(uri_str, content, out);
self.collect_invalid_class_kind_diagnostics(uri_str, content, out);
}

/// Collect all type mismatch diagnostics: argument types, return
/// types, and property assignment types.
///
/// This is a convenience entry point that groups the three
/// `type_mismatch_*` collectors. The individual methods remain
/// available for selective use (e.g. in `analyse.rs`).
pub fn collect_type_mismatch_diagnostics(
&self,
uri_str: &str,
content: &str,
out: &mut Vec<Diagnostic>,
) {
self.collect_argument_type_diagnostics(uri_str, content, out);
self.collect_return_type_diagnostics(uri_str, content, out);
self.collect_property_type_diagnostics(uri_str, content, out);
}
}

/// Check whether a cached PHPStan diagnostic is stale given the current
Expand Down
Loading
Loading