mirror of
https://github.com/danog/psalm.git
synced 2024-11-27 04:45:20 +01:00
Fix #2184 - execute __invoke methods explicitly
This commit is contained in:
parent
9af8a9ac38
commit
4ec22cffca
@ -174,29 +174,44 @@ class FunctionCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expressio
|
||||
) {
|
||||
$invalid_function_call_types[] = (string)$var_type_part;
|
||||
} else {
|
||||
if (self::checkMethodArgs(
|
||||
$var_type_part->value . '::__invoke',
|
||||
$stmt->args,
|
||||
$class_template_params,
|
||||
$context,
|
||||
new CodeLocation($statements_analyzer->getSource(), $stmt),
|
||||
$statements_analyzer
|
||||
) === false) {
|
||||
return;
|
||||
$fake_method_call = new PhpParser\Node\Expr\MethodCall(
|
||||
$stmt->name,
|
||||
new PhpParser\Node\Identifier('__invoke', $stmt->name->getAttributes()),
|
||||
$stmt->args
|
||||
);
|
||||
|
||||
$suppressed_issues = $statements_analyzer->getSuppressedIssues();
|
||||
|
||||
if (!in_array('PossiblyNullReference', $suppressed_issues, true)) {
|
||||
$statements_analyzer->addSuppressedIssues(['PossiblyNullReference']);
|
||||
}
|
||||
|
||||
$invokable_return_type = $codebase->methods->getMethodReturnType(
|
||||
$var_type_part->value . '::__invoke',
|
||||
$var_type_part->value
|
||||
if (!in_array('InternalMethod', $suppressed_issues, true)) {
|
||||
$statements_analyzer->addSuppressedIssues(['InternalMethod']);
|
||||
}
|
||||
|
||||
\Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze(
|
||||
$statements_analyzer,
|
||||
$fake_method_call,
|
||||
$context,
|
||||
false
|
||||
);
|
||||
|
||||
if (!in_array('PossiblyNullReference', $suppressed_issues, true)) {
|
||||
$statements_analyzer->removeSuppressedIssues(['PossiblyNullReference']);
|
||||
}
|
||||
|
||||
if (!in_array('InternalMethod', $suppressed_issues, true)) {
|
||||
$statements_analyzer->removeSuppressedIssues(['InternalMethod']);
|
||||
}
|
||||
|
||||
if (isset($stmt->inferredType)) {
|
||||
$stmt->inferredType = Type::combineUnionTypes(
|
||||
$invokable_return_type ?: Type::getMixed(),
|
||||
$fake_method_call->inferredType ?? Type::getMixed(),
|
||||
$stmt->inferredType
|
||||
);
|
||||
} else {
|
||||
$stmt->inferredType = $invokable_return_type ?: Type::getMixed();
|
||||
$stmt->inferredType = $fake_method_call->inferredType ?? Type::getMixed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1722,6 +1722,48 @@ class ClassTemplateTest extends TestCase
|
||||
}
|
||||
}'
|
||||
],
|
||||
'templatedInvoke' => [
|
||||
'<?php
|
||||
/**
|
||||
* @template T
|
||||
*/
|
||||
class Foo {
|
||||
/** @var T */
|
||||
private $value;
|
||||
|
||||
/** @param T $val */
|
||||
public function __construct($val) {
|
||||
$this->value = $val;
|
||||
}
|
||||
|
||||
/** @return T */
|
||||
public function get() {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param T $val
|
||||
* @return Foo<T>
|
||||
*/
|
||||
public function __invoke($val) {
|
||||
return new static($val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param T $val
|
||||
* @return Foo<T>
|
||||
*/
|
||||
public function create($val) {
|
||||
return new static($val);
|
||||
}
|
||||
}
|
||||
|
||||
function bar(string $s) : string {
|
||||
$foo = new Foo($s);
|
||||
$bar = $foo($s);
|
||||
return $bar->get();
|
||||
}'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user