1
0
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:
Matthew Brown 2019-09-29 16:01:33 -04:00
parent 9af8a9ac38
commit 4ec22cffca
2 changed files with 71 additions and 14 deletions

View File

@ -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();
}
}
}

View File

@ -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();
}'
],
];
}