Skip to content

Commit 8fc3672

Browse files
AJenbocalebdw
authored andcommitted
Add test and clean ups
Signed-off-by: Anders Jenbo <anders@jenbo.dk>
1 parent 60e189e commit 8fc3672

3 files changed

Lines changed: 30 additions & 2 deletions

File tree

docs/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4545
- **Returning to a backgrounded editor stays responsive.** When an editor regains focus it re-reports every file in the workspace as changed in one large batch. Processing that batch could stall the server while it re-read thousands of files from disk. The batch is now handled off the main loop and skips files that were never loaded, so the editor stays responsive.
4646
- **Inherited members no longer briefly flagged as unknown after opening a project.** A method or property inherited from a vendor base class (for example the base methods of a framework controller) could be reported as an unknown member right after a file opened, even though hover resolved it correctly, and the error went away when the file was closed and reopened. Such members now resolve as soon as indexing finishes.
4747
- **Named arguments are matched to parameters by name.** Calls that pass arguments by name (`f(c: 3)`) are now bound to the parameters they actually target instead of by their position in the call. Conditional return types resolve correctly when the deciding argument is passed by name out of order, a "missing required argument" error is now reported when a named argument fills an optional parameter but leaves a required one unsupplied, and pass-by-reference type inference seeds the right variable.
48-
- **Argument-count false positives.** Extra arguments to a class with no constructor are no longer flagged (PHP accepts them), and namespaced calls to overloaded built-ins written with a leading backslash (`\mt_rand()`) are no longer measured against the wrong minimum.
48+
- **Argument-count false positives.** Extra arguments to a class with no constructor are no longer flagged (PHP accepts them), and namespaced calls to overloaded built-ins written with a leading backslash (`\mt_rand()`) are no longer measured against the wrong minimum. Immediately invoking the callable returned by a function or method (`makeHandler($a, $b)($request)`) now checks the inner call's arguments against the returned callable's own signature instead of the outer call's, fixing both false argument-count errors and wrong inlay hint parameter names on the invocation. Contributed by @calebdw in https://github.com/AJenbo/phpantom_lsp/pull/191.
4949
- **`@var` annotations no longer leak between functions.** A `/** @var T $x */` annotation in one function used to suppress "undefined variable" warnings for that name everywhere in the file; it is now scoped to the function it appears in.
5050
- **Type resolution through chained and untyped access.** Null-safe call chains such as `$a->b?->c()` resolve through the full receiver. Array access on a value of unknown type resolves to `mixed`, so `$x = $arr['key'] ?? 5` no longer produces spurious type errors. `foreach` element types resolve through interfaces that reach a known iterable several hops away. Nested array-shape narrowing (`$a["x"]["y"]`) no longer targets the wrong key.
5151
- **`self` references inside class-level attributes resolve.** A `self::`, `static::`, or `parent::` reference inside an attribute attached to a class (for example `#[Route(name: self::ROUTE)]`) is now resolved against the class it decorates, so the referenced constant or member is no longer reported as unresolvable.

src/completion/call_resolution.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2850,7 +2850,7 @@ fn callable_type_as_target(return_type: &PhpType) -> Option<ResolvedCallableTarg
28502850
.iter()
28512851
.enumerate()
28522852
.map(|(i, p)| ParameterInfo {
2853-
name: crate::atom::atom(&format!("$param{}", i + 1)),
2853+
name: atom(&format!("$param{}", i + 1)),
28542854
is_required: !p.optional && !p.variadic,
28552855
type_hint: Some(p.type_hint.clone()),
28562856
native_type_hint: None,

tests/integration/inlay_hints.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,3 +1420,31 @@ makeCallable('1', '2')('test');
14201420
a_count, line6_labels
14211421
);
14221422
}
1423+
1424+
#[tokio::test]
1425+
async fn callable_return_invocation_fully_qualified_closure() {
1426+
// The fully-qualified `\Closure` return type spelling must be
1427+
// recognised the same way as bare `Closure` and `callable`.
1428+
let backend = create_test_backend();
1429+
let uri = Url::parse("file:///test/closure_invoke.php").unwrap();
1430+
let text = r#"<?php
1431+
function makeClosure(string $a, string $b): \Closure
1432+
{
1433+
return fn (string $c) => "$a $b $c";
1434+
}
1435+
1436+
makeClosure('1', '2')('test');
1437+
"#;
1438+
1439+
let hints = inlay_hints_for(&backend, &uri, text).await;
1440+
1441+
let line6_hints = hints_at_line(&hints, 6);
1442+
let line6_labels: Vec<String> = line6_hints.iter().map(|h| hint_label(h)).collect();
1443+
1444+
let a_count = line6_labels.iter().filter(|l| *l == "a:").count();
1445+
assert_eq!(
1446+
a_count, 1,
1447+
"Should have exactly 1 'a:' hint (outer call only), got {}: {:?}",
1448+
a_count, line6_labels
1449+
);
1450+
}

0 commit comments

Comments
 (0)