2020-07-08 21:51:02 +02:00
|
|
|
<?php
|
|
|
|
namespace Psalm\Tests;
|
|
|
|
|
2020-07-08 22:24:20 +02:00
|
|
|
class IfThisIsTest extends TestCase
|
2020-07-08 21:51:02 +02:00
|
|
|
{
|
|
|
|
use Traits\ValidCodeAnalysisTestTrait;
|
|
|
|
use Traits\InvalidCodeAnalysisTestTrait;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return iterable<string,array{string,assertions?:array<string,string>,error_levels?:string[]}>
|
|
|
|
*/
|
|
|
|
public function providerValidCodeParse()
|
|
|
|
{
|
|
|
|
return [
|
|
|
|
'worksAfterConvert' => [
|
|
|
|
'<?php
|
|
|
|
interface I {
|
|
|
|
/**
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function test();
|
|
|
|
}
|
|
|
|
|
|
|
|
class F implements I
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @psalm-self-out I
|
|
|
|
* @return void
|
|
|
|
*/
|
2020-07-12 22:06:03 +02:00
|
|
|
public function convert() {}
|
2020-07-08 21:51:02 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @psalm-if-this-is I
|
|
|
|
* @return void
|
|
|
|
*/
|
2020-07-12 22:06:03 +02:00
|
|
|
public function test() {}
|
2020-07-08 21:51:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$f = new F();
|
|
|
|
$f->convert();
|
|
|
|
$f->test();
|
|
|
|
'
|
2020-07-12 22:06:03 +02:00
|
|
|
],
|
|
|
|
'withTemplate' => [
|
|
|
|
'<?php
|
|
|
|
class Frozen {}
|
|
|
|
class Unfrozen {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @template T of Frozen|Unfrozen
|
|
|
|
*/
|
|
|
|
class Foo
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var T
|
|
|
|
*/
|
|
|
|
private $state;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param T $state
|
|
|
|
*/
|
|
|
|
public function __construct($state)
|
|
|
|
{
|
|
|
|
$this->state = $state;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $name
|
|
|
|
* @param mixed $val
|
|
|
|
* @psalm-if-this-is Foo<Unfrozen>
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function set($name, $val)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return Foo<Frozen>
|
|
|
|
*/
|
|
|
|
public function freeze()
|
|
|
|
{
|
|
|
|
/** @var Foo<Frozen> */
|
|
|
|
$f = clone $this;
|
|
|
|
return $f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$f = new Foo(new Unfrozen());
|
|
|
|
$f->set("asd", 10);
|
|
|
|
'
|
|
|
|
],
|
|
|
|
'subclass' => [
|
|
|
|
'<?php
|
|
|
|
class G
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @psalm-if-this-is G
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function test() {}
|
|
|
|
}
|
|
|
|
|
|
|
|
class F extends G
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
$f = new F();
|
|
|
|
$f->test();
|
|
|
|
'
|
2020-07-08 21:51:02 +02:00
|
|
|
]
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return array<string, array{0: string, error_message: string}>
|
|
|
|
*/
|
|
|
|
public function providerInvalidCodeParse()
|
|
|
|
{
|
|
|
|
return [
|
|
|
|
'blocksWithoutConvert' => [
|
|
|
|
'<?php
|
|
|
|
interface I {
|
|
|
|
/**
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function test();
|
|
|
|
}
|
|
|
|
|
|
|
|
class F implements I
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @psalm-if-this-is I
|
|
|
|
* @return void
|
|
|
|
*/
|
2020-07-12 22:06:03 +02:00
|
|
|
public function test() {}
|
2020-07-08 21:51:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$f = new F();
|
|
|
|
$f->test();
|
|
|
|
',
|
|
|
|
'error_message' => 'IfThisIsMismatch'
|
2020-07-12 22:06:03 +02:00
|
|
|
],
|
|
|
|
'failsWithWrongTemplate' => [
|
|
|
|
'<?php
|
|
|
|
class Frozen {}
|
|
|
|
class Unfrozen {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @template T of Frozen|Unfrozen
|
|
|
|
*/
|
|
|
|
class Foo
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var T
|
|
|
|
*/
|
|
|
|
private $state;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param T $state
|
|
|
|
*/
|
|
|
|
public function __construct($state)
|
|
|
|
{
|
|
|
|
$this->state = $state;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $name
|
|
|
|
* @param mixed $val
|
|
|
|
* @psalm-if-this-is Foo<Unfrozen>
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function set($name, $val) {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return Foo<Frozen>
|
|
|
|
*/
|
|
|
|
public function freeze()
|
|
|
|
{
|
|
|
|
/** @var Foo<Frozen> */
|
|
|
|
$f = clone $this;
|
|
|
|
return $f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$f = new Foo(new Unfrozen());
|
|
|
|
$f->set("asd", 10);
|
|
|
|
$g = $f->freeze();
|
|
|
|
$g->set("asd", 20); // Fails
|
|
|
|
',
|
|
|
|
'error_message' => 'IfThisIsMismatch'
|
|
|
|
],
|
2020-07-08 21:51:02 +02:00
|
|
|
];
|
|
|
|
}
|
|
|
|
}
|