1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00

Closure basically implements callable

This commit is contained in:
Matthew Brown 2016-10-20 18:05:28 -04:00
parent 07636468a2
commit d71d439e25
5 changed files with 20 additions and 28 deletions

View File

@ -161,6 +161,10 @@ class ClassChecker extends ClassLikeChecker
{ {
$interface_id = strtolower($interface); $interface_id = strtolower($interface);
if ($interface_id === 'callable' && $absolute_class === 'Closure') {
return true;
}
if (isset(self::$class_implements[$absolute_class][$interface_id])) { if (isset(self::$class_implements[$absolute_class][$interface_id])) {
return true; return true;
} }

View File

@ -302,7 +302,8 @@ class FunctionChecker extends FunctionLikeChecker
$function_call_arg = $call_args[$function_index]; $function_call_arg = $call_args[$function_index];
if ($function_call_arg->value instanceof PhpParser\Node\Expr\Closure) { if ($function_call_arg->value instanceof PhpParser\Node\Expr\Closure) {
$closure_return_types = \Psalm\EffectsAnalyser::getReturnTypes($function_call_arg->value->stmts, true); $closure_yield_types = [];
$closure_return_types = \Psalm\EffectsAnalyser::getReturnTypes($function_call_arg->value->stmts, $closure_yield_types, true);
if (!$closure_return_types) { if (!$closure_return_types) {
if (IssueBuffer::accepts( if (IssueBuffer::accepts(

View File

@ -1116,6 +1116,8 @@ class StatementsChecker
$closure_checker->check($use_context, $context->check_methods); $closure_checker->check($use_context, $context->check_methods);
$stmt->inferredType = Type::getClosure();
} elseif ($stmt instanceof PhpParser\Node\Expr\ArrayDimFetch) { } elseif ($stmt instanceof PhpParser\Node\Expr\ArrayDimFetch) {
if ($this->checkArrayAccess($stmt, $context, $array_assignment, $assignment_key_type, $assignment_value_type, $assignment_key_value) === false) { if ($this->checkArrayAccess($stmt, $context, $array_assignment, $assignment_key_type, $assignment_value_type, $assignment_key_value) === false) {
return false; return false;

View File

@ -254,6 +254,14 @@ abstract class Type
return new Union([$type]); return new Union([$type]);
} }
/** @return Type\Union */
public static function getClosure()
{
$type = new Atomic('Closure');
return new Union([$type]);
}
/** @return Type\Union */ /** @return Type\Union */
public static function getArray() public static function getArray()
{ {

View File

@ -153,10 +153,10 @@ class Php70Test extends PHPUnit_Framework_TestCase
public function testGeneratorWithReturn() public function testGeneratorWithReturn()
{ {
$this->markTestIncomplete('Not yet supported');
$stmts = self::$_parser->parse('<?php $stmts = self::$_parser->parse('<?php
/** /**
* @return array<int,int> * @return Generator<int,int>
* @psalm-generator-return string
*/ */
function foo(int $i) : Generator { function foo(int $i) : Generator {
if ($i === 1) { if ($i === 1) {
@ -170,31 +170,6 @@ class Php70Test extends PHPUnit_Framework_TestCase
$file_checker = new \Psalm\Checker\FileChecker('somefile.php', $stmts); $file_checker = new \Psalm\Checker\FileChecker('somefile.php', $stmts);
$context = new Context('somefile.php'); $context = new Context('somefile.php');
$file_checker->check(true, true, $context); $file_checker->check(true, true, $context);
$this->assertEquals('array<int,int>', (string) $context->vars_in_scope['$gen']);
$this->assertEquals('int', (string) $context->vars_in_scope['$gen2']);
}
public function testClosureCall()
{
$this->markTestIncomplete('Not yet supported');
$stmts = self::$_parser->parse('<?php
class A {private $x = 1;}
// Pre PHP 7 code
$getXCB = function() {return $this->x;};
$getX = $getXCB->bindTo(new A, "A"); // intermediate closure
$a = $getX();
// PHP 7+ code
$getX = function() {return $this->x;};
$b = $getX->call(new A);
');
$file_checker = new \Psalm\Checker\FileChecker('somefile.php', $stmts);
$context = new Context('somefile.php');
$file_checker->check(true, true, $context);
$this->assertEquals('mixed', (string) $context->vars_in_scope['$a']);
$this->assertEquals('mixed', (string) $context->vars_in_scope['$b']);
} }
public function testGeneratorDelegation() public function testGeneratorDelegation()
@ -202,6 +177,7 @@ class Php70Test extends PHPUnit_Framework_TestCase
$stmts = self::$_parser->parse('<?php $stmts = self::$_parser->parse('<?php
/** /**
* @return Generator<int,int> * @return Generator<int,int>
* @psalm-generator-return int
*/ */
function count_to_ten() : Generator { function count_to_ten() : Generator {
yield 1; yield 1;
@ -229,6 +205,7 @@ class Php70Test extends PHPUnit_Framework_TestCase
/** /**
* @return Generator<int,int> * @return Generator<int,int>
* @psalm-generator-return int
*/ */
function nine_ten() : Generator { function nine_ten() : Generator {
yield 9; yield 9;