1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00
psalm/tests/NativeIntersectionsTest.php
Pete Walker a3bdf1ba8c
feat: Handle native intersection types
Adds native intersection type handling to psalm, removing the previous `UnexpectedValueException`.

Where an intersection is found in the parse tree, the types are resolved using the existing `Type::intersectUnionTypes` function, which I assume is being used when they're encountered in the existing docblock annotations.

I've added a handful of tests to cover this, but they're certainly not exhaustive. Are there any specific edge cases I should target?

This change feels way too simple... so apologies if I've missed something fundamental..!
2022-01-21 12:59:55 +00:00

109 lines
3.3 KiB
PHP

<?php
namespace Psalm\Tests;
use Psalm\Tests\Traits\InvalidCodeAnalysisTestTrait;
use Psalm\Tests\Traits\ValidCodeAnalysisTestTrait;
class NativeIntersectionsTest extends TestCase
{
use InvalidCodeAnalysisTestTrait;
use ValidCodeAnalysisTestTrait;
/**
* @return iterable<string,array{code:string,assertions?:array<string,string>,ignored_issues?:list<string>}>
*/
public function providerValidCodeParse(): iterable
{
return [
'nativeTypeIntersectionInConstructor' => [
'code' => '<?php
interface A {
}
interface B {
}
class Foo {
public function __construct(private A&B $self) {}
public function self(): A&B
{
return $this->self;
}
}',
'assertions' => [],
'ignored_issues' => [],
'php_version' => '8.1'
],
'nativeTypeIntersectionAsArgument' => [
'code' => '<?php
interface A {
function foo(): void;
}
interface B {
}
class C implements A, B {
function foo(): void {
}
}
function test(A&B $in): void {
$in->foo();
}
test(new C());
',
'assertions' => [],
'ignored_issues' => [],
'php_version' => '8.1'
],
];
}
/**
* @return iterable<string,array{code:string,error_message:string,ignored_issues?:list<string>,php_version?:string}>
*/
public function providerInvalidCodeParse(): iterable
{
return [
'invalidNativeIntersectionArgument' => [
'code' => '<?php
interface A {
function foo(): void;
}
interface B {
}
class C implements A {
function foo(): void {
}
}
function test(A&B $in): void {
$in->foo();
}
test(new C());
',
'error_message' => 'InvalidArgument',
'ignored_issues' => [],
'php_version' => '8.1'
],
'mismatchDocblockNativeIntersectionArgument' => [
'code' => '<?php
interface A {
function foo(): void;
}
interface B {
}
interface C {
}
/**
* @param A&C $in
*/
function test(A&B $in): void {
$in->foo();
}
',
'error_message' => 'MismatchingDocblockParamType',
'ignored_issues' => [],
'php_version' => '8.1'
],
];
}
}