2016-12-09 18:07:47 +01:00
< ? php
2021-12-15 04:58:32 +01:00
2016-12-09 18:07:47 +01:00
namespace Psalm\Tests ;
2021-12-04 21:55:53 +01:00
use Psalm\Tests\Traits\InvalidCodeAnalysisTestTrait ;
use Psalm\Tests\Traits\ValidCodeAnalysisTestTrait ;
2022-11-26 17:26:36 +01:00
use const DIRECTORY_SEPARATOR ;
2017-04-25 05:45:02 +02:00
class ArgTest extends TestCase
2016-12-09 18:07:47 +01:00
{
2021-12-04 21:55:53 +01:00
use InvalidCodeAnalysisTestTrait ;
use ValidCodeAnalysisTestTrait ;
2017-01-02 21:31:18 +01:00
2020-09-12 17:24:05 +02:00
public function providerValidCodeParse () : iterable
2016-12-09 18:07:47 +01:00
{
2017-04-25 05:45:02 +02:00
return [
2020-10-15 00:51:15 +02:00
'argumentUnpackingLiteral' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-15 00:51:15 +02:00
function add ( int $a , int $b , int $c ) : int {
return $a + $b + $c ;
}
echo add ( 1 , ... [ 2 , 3 ]); ' ,
],
'arrayPushArgumentUnpackingWithGoodArg' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-15 00:51:15 +02:00
$a = [ " foo " ];
$b = [ " foo " , " bar " ];
array_push ( $a , ... $b ); ' ,
'assertions' => [
'$a' => 'non-empty-list<string>' ,
],
],
'arrayMergeArgumentUnpacking' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-15 00:51:15 +02:00
$a = [[ 1 , 2 ]];
$b = array_merge ([], ... $a ); ' ,
'assertions' => [
2022-11-12 02:14:21 +01:00
'$b===' => 'list{1, 2}' ,
2020-10-15 00:51:15 +02:00
],
],
'preserveTypesWhenUnpacking' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-15 00:51:15 +02:00
/**
* @ return array < int , array < int , string >>
*/
function getData () : array
{
return [
[ " a " , " b " ],
[ " c " , " d " ]
];
}
/**
* @ return array < int , string >
*/
function f1 () : array
{
$data = getData ();
return array_merge ( $data [ 0 ], $data [ 1 ]);
}
/**
* @ return array < int , string >
*/
function f2 () : array
{
$data = getData ();
return array_merge ( ... $data );
}
/**
* @ return array < int , string >
*/
function f3 () : array
{
$data = getData ();
return array_merge ([], ... $data );
} ' ,
],
'unpackArg' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-15 00:51:15 +02:00
function Foo ( string $a , string ... $b ) : void {}
2021-03-23 00:58:22 +01:00
/** @return array<array-key, string> */
2020-10-15 00:51:15 +02:00
function Baz ( string ... $c ) {
Foo ( ... $c );
return $c ;
} ' ,
],
'unpackByRefArg' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-15 00:51:15 +02:00
function example ( int &... $x ) : void {}
$y = 0 ;
example ( $y );
$z = [ 0 ];
example ( ... $z ); ' ,
'assertions' => [
'$y' => 'int' ,
'$z' => 'array<int, int>' ,
],
],
2017-04-25 05:45:02 +02:00
'callMapClassOptionalArg' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-06-11 18:19:27 +02:00
class Hello {}
$m = new ReflectionMethod ( Hello :: class , " goodbye " );
2018-02-07 02:50:32 +01:00
$m -> invoke ( null , " cool " ); ' ,
2017-05-27 02:05:57 +02:00
],
2017-10-28 19:56:29 +02:00
'sortFunctions' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2017-10-28 19:56:29 +02:00
$a = [ " b " => 5 , " a " => 8 ];
ksort ( $a );
$b = [ " b " => 5 , " a " => 8 ];
sort ( $b );
2022-04-23 18:00:38 +02:00
$c = [];
sort ( $c );
2017-10-28 19:56:29 +02:00
' ,
'assertions' => [
2022-11-12 02:14:21 +01:00
'$a' => 'array{a: int, b: int}' ,
2022-04-23 18:00:38 +02:00
'$b' => 'non-empty-list<int>' ,
2022-05-28 22:19:49 +02:00
'$c' => 'list<never>' ,
2017-10-28 19:56:29 +02:00
],
],
'arrayModificationFunctions' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2017-10-28 19:56:29 +02:00
$a = [ " b " => 5 , " a " => 8 ];
2017-12-09 20:53:39 +01:00
array_unshift ( $a , ( bool ) rand ( 0 , 1 ));
2017-10-28 19:56:29 +02:00
$b = [ " b " => 5 , " a " => 8 ];
2017-12-09 20:53:39 +01:00
array_push ( $b , ( bool ) rand ( 0 , 1 ));
2017-10-28 19:56:29 +02:00
' ,
'assertions' => [
2019-12-29 16:29:03 +01:00
'$a' => 'non-empty-array<int|string, bool|int>' ,
'$b' => 'non-empty-array<int|string, bool|int>' ,
2017-10-28 19:56:29 +02:00
],
],
2017-10-28 21:33:29 +02:00
'byRefArgAssignment' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2017-10-28 21:33:29 +02:00
$a = [ " hello " , " goodbye " ];
shuffle ( $a );
$a = [ 0 , 1 ]; ' ,
],
2018-06-04 02:24:23 +02:00
'correctOrderValidation' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2018-06-04 02:24:23 +02:00
function getString ( int $i ) : string {
return rand ( 0 , 1 ) ? " hello " : " " ;
}
function takesInt ( int $i ) : void {}
$i = rand ( 0 , 10 );
if ( ! ( $i = getString ( $i ))) {} ' ,
],
2018-06-30 16:38:37 +02:00
'allowNullInObjectUnion' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2018-06-30 16:38:37 +02:00
/**
* @ param string | null | object $b
*/
function foo ( $b ) : void {}
foo ( null ); ' ,
],
2021-12-19 12:17:25 +01:00
'allowArrayIntScalarForArrayStringWithArgumentTypeCoercionIgnored' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-12-19 12:17:25 +01:00
/** @param array<array-key> $arr */
2019-03-19 21:12:32 +01:00
function foo ( array $arr ) : void {
}
/** @return array<int, scalar> */
function bar () : array {
return [];
}
2021-12-19 12:17:25 +01:00
/** @psalm-suppress ArgumentTypeCoercion */
2019-03-19 21:45:26 +01:00
foo ( bar ()); ' ,
],
2021-12-19 12:17:25 +01:00
'allowArrayScalarForArrayStringWithArgumentTypeCoercionIgnored' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php declare ( strict_types = 1 );
2019-03-19 21:45:26 +01:00
/** @param array<string> $arr */
function foo ( array $arr ) : void {}
/** @return array<int, scalar> */
function bar () : array {
return [];
}
2021-12-19 12:17:25 +01:00
/** @psalm-suppress ArgumentTypeCoercion */
2019-03-19 21:12:32 +01:00
foo ( bar ()); ' ,
2019-03-23 19:27:54 +01:00
],
2020-01-21 16:13:37 +01:00
'unpackObjectlikeListArgs' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-01-21 16:13:37 +01:00
$a = [ new DateTime (), 1 ];
function f ( DateTime $d , int $a ) : void {}
f ( ... $a ); ' ,
],
2020-03-17 21:16:58 +01:00
'unpackWithoutAlteringArray' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-03-17 21:16:58 +01:00
function takeVariadicInts ( int ... $inputs ) : void {}
$a = [ 3 , 5 , 7 ];
takeVariadicInts ( ... $a ); ' ,
2022-01-13 19:49:37 +01:00
'assertions' => [
2022-12-18 17:15:15 +01:00
'$a' => 'non-empty-list<int>' ,
],
2020-03-17 21:16:58 +01:00
],
2020-03-17 21:30:03 +01:00
'iterableSplat' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-03-23 00:58:22 +01:00
/** @param iterable<int, mixed> $args */
2020-03-17 21:30:03 +01:00
function foo ( iterable $args ) : int {
return intval ( ... $args );
}
2021-03-23 00:58:22 +01:00
/** @param ArrayIterator<int, mixed> $args */
2020-03-17 21:30:03 +01:00
function bar ( ArrayIterator $args ) : int {
return intval ( ... $args );
} ' ,
],
2020-10-08 15:51:27 +02:00
'unpackListWithOptional' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-08 15:51:27 +02:00
function foo ( string ... $rest ) : void {}
$rest = [ " zzz " ];
if ( rand ( 0 , 1 )) {
$rest [] = " xxx " ;
}
2022-12-18 17:15:15 +01:00
foo ( " first " , ... $rest ); ' ,
2020-10-08 15:51:27 +02:00
],
2020-10-03 02:27:01 +02:00
'useNamedArguments' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-03 02:27:01 +02:00
class CustomerData {
public function __construct (
public string $name ,
public string $email ,
public int $age ,
) {}
}
/**
2022-11-12 02:14:21 +01:00
* @ param array { age : int , name : string , email : string } $input
2020-10-03 02:27:01 +02:00
*/
function foo ( array $input ) : CustomerData {
return new CustomerData (
age : $input [ " age " ],
name : $input [ " name " ],
email : $input [ " email " ],
);
2022-12-18 17:15:15 +01:00
} ' ,
2020-10-03 02:27:01 +02:00
],
'useNamedArgumentsSimple' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-03 02:27:01 +02:00
function takesArguments ( string $name , int $age ) : void {}
takesArguments ( name : " hello " , age : 5 );
2022-12-18 17:15:15 +01:00
takesArguments ( age : 5 , name : " hello " ); ' ,
2020-10-03 02:27:01 +02:00
],
'useNamedArgumentsSpread' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-03 02:27:01 +02:00
function takesArguments ( string $name , int $age ) : void {}
$args = [ " name " => " hello " , " age " => 5 ];
takesArguments ( ... $args ); ' ,
2022-01-13 19:49:37 +01:00
'assertions' => [],
'ignored_issues' => [],
2022-12-18 17:15:15 +01:00
'php_version' => '8.0' ,
2020-10-03 02:27:01 +02:00
],
2020-11-16 21:49:27 +01:00
'useNamedVariadicArguments' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-11-16 21:49:27 +01:00
function takesArguments ( int ... $args ) : void {}
takesArguments ( age : 5 ); ' ,
2022-01-13 19:49:37 +01:00
'assertions' => [],
'ignored_issues' => [],
2022-12-18 17:15:15 +01:00
'php_version' => '8.0' ,
2020-11-16 21:49:27 +01:00
],
2021-03-22 14:08:05 +01:00
'useUnpackedNamedVariadicArguments' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-03-22 14:08:05 +01:00
function takesArguments ( int ... $args ) : void {}
takesArguments ( ... [ " age " => 5 ]); ' ,
2022-01-13 19:49:37 +01:00
'assertions' => [],
'ignored_issues' => [],
2022-12-18 17:15:15 +01:00
'php_version' => '8.0' ,
2021-03-22 14:08:05 +01:00
],
2021-01-22 06:20:51 +01:00
'variadicArgsOptional' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-01-22 06:20:51 +01:00
bar ( ... [ " aaaaa " ]);
2022-12-18 17:15:15 +01:00
function bar ( string $p1 , int $p3 = 10 ) : void {} ' ,
2021-01-22 06:20:51 +01:00
],
2021-01-28 04:28:33 +01:00
'mkdirNamedParameters' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php declare ( strict_types = 1 );
2021-01-28 04:28:33 +01:00
mkdir ( " /var/test/123 " , recursive : true ); ' ,
2022-01-13 19:49:37 +01:00
'assertions' => [],
'ignored_issues' => [],
2022-12-18 17:15:15 +01:00
'php_version' => '8.0' ,
2021-01-28 04:28:33 +01:00
],
2021-03-23 00:58:22 +01:00
'variadicArgumentWithNoNamedArgumentsIsList' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-03-23 00:58:22 +01:00
class A {
/**
* @ no - named - arguments
* @ psalm - return list < int >
*/
public function foo ( int ... $values ) : array
{
return $values ;
}
}
' ,
],
2022-11-05 22:34:42 +01:00
'SealedAcceptSealed' => [
'code' => ' < ? php
2022-11-12 02:14:21 +01:00
/** @param array{test: string} $a */
2022-11-05 22:34:42 +01:00
function a ( array $a ) : string {
return $a [ " test " ];
}
$sealed = [ " test " => " str " ];
a ( $sealed );
' ,
],
2022-10-22 08:48:18 +02:00
'variadicCallbackArgsCountMatch' => [
2022-11-08 10:25:04 +01:00
'code' => ' < ? php
2022-10-22 08:48:18 +02:00
/**
* @ param callable ( string , string ) : void $callback
* @ return void
*/
function caller ( $callback ) {}
/**
* @ param string ... $bar
* @ return void
*/
function foo ( ... $bar ) {}
caller ( " foo " ); ' ,
],
'variadicCallableArgsCountMatch' => [
2022-11-08 10:25:04 +01:00
'code' => ' < ? php
2022-10-22 08:48:18 +02:00
/**
* @ param callable ( string , ... int ) : void $callback
* @ return void
*/
function var_caller ( $callback ) {}
/**
* @ param string $a
* @ param int $b
* @ param int $c
* @ return void
*/
function foo ( $a , $b , $c ) {}
var_caller ( " foo " ); ' ,
],
2017-04-25 05:45:02 +02:00
];
2016-12-09 18:07:47 +01:00
}
2017-04-08 15:28:02 +02:00
2020-09-12 17:24:05 +02:00
public function providerInvalidCodeParse () : iterable
2017-04-08 15:28:02 +02:00
{
2017-04-25 05:45:02 +02:00
return [
2020-10-15 00:51:15 +02:00
'arrayPushArgumentUnpackingWithBadArg' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-15 00:51:15 +02:00
$a = [];
$b = " hello " ;
$a [] = " foo " ;
array_push ( $a , ... $b ); ' ,
'error_message' => 'InvalidArgument' ,
],
2017-04-25 05:45:02 +02:00
'possiblyInvalidArgument' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2017-04-25 05:45:02 +02:00
$foo = [
" a " ,
[ " b " ],
];
2017-10-28 19:56:29 +02:00
2017-04-25 05:45:02 +02:00
$a = array_map (
2018-01-11 21:50:45 +01:00
function ( string $uuid ) : string {
2017-04-25 05:45:02 +02:00
return $uuid ;
},
$foo [ rand ( 0 , 1 )]
); ' ,
2017-05-27 02:05:57 +02:00
'error_message' => 'PossiblyInvalidArgument' ,
],
2018-05-01 20:26:57 +02:00
'possiblyInvalidArgumentWithOverlap' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2018-05-01 20:26:57 +02:00
class A {}
class B {}
class C {}
$foo = rand ( 0 , 1 ) ? new A : new B ;
/** @param B|C $b */
function bar ( $b ) : void {}
bar ( $foo ); ' ,
'error_message' => 'PossiblyInvalidArgument' ,
],
2020-03-23 17:08:05 +01:00
'possiblyInvalidArgumentWithMixed' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php declare ( strict_types = 1 );
2020-03-23 17:08:05 +01:00
/**
* @ psalm - suppress MissingParamType
* @ psalm - suppress MixedArgument
*/
function foo ( $a ) : void {
if ( rand ( 0 , 1 )) {
$a = 0 ;
}
echo strlen ( $a );
} ' ,
'error_message' => 'PossiblyInvalidArgument' ,
],
2020-09-30 18:28:13 +02:00
'expectsNonNullAndPassedPossiblyNull' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-09-30 18:28:13 +02:00
/**
* @ param mixed | null $mixed_or_null
*/
function foo ( $mixed , $mixed_or_null ) : void {
/**
* @ psalm - suppress MixedArgument
*/
new Exception ( $mixed_or_null );
} ' ,
2022-12-18 17:15:15 +01:00
'error_message' => 'PossiblyNullArgument' ,
2020-09-30 18:28:13 +02:00
],
2020-10-03 02:27:01 +02:00
'useInvalidNamedArgument' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-03 02:27:01 +02:00
class CustomerData {
public function __construct (
public string $name ,
public string $email ,
public int $age ,
) {}
}
/**
2022-11-12 02:14:21 +01:00
* @ param array { age : int , name : string , email : string } $input
2020-10-03 02:27:01 +02:00
*/
function foo ( array $input ) : CustomerData {
return new CustomerData (
aage : $input [ " age " ],
name : $input [ " name " ],
email : $input [ " email " ],
);
} ' ,
2022-12-18 17:15:15 +01:00
'error_message' => 'InvalidNamedArgument' ,
2020-10-03 02:27:01 +02:00
],
2021-12-11 21:37:15 +01:00
'usePositionalArgAfterNamed' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-12-11 21:37:15 +01:00
final class Person
{
public function __construct (
public string $name ,
public int $age ,
) { }
}
new Person ( name : " " , 0 ); ' ,
2022-12-18 17:15:15 +01:00
'error_message' => 'InvalidNamedArgument' ,
2021-12-11 21:37:15 +01:00
],
2021-03-22 14:08:05 +01:00
'useUnpackedInvalidNamedArgument' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-03-22 14:08:05 +01:00
class CustomerData {
public function __construct (
public string $name ,
public string $email ,
public int $age ,
) {}
}
/**
2022-11-12 02:14:21 +01:00
* @ param array { aage : int , name : string , email : string } $input
2021-03-22 14:08:05 +01:00
*/
function foo ( array $input ) : CustomerData {
return new CustomerData ( ... $input );
} ' ,
'error_message' => 'InvalidNamedArgument' ,
2022-01-13 19:49:37 +01:00
'ignored_issues' => [],
2022-12-18 17:15:15 +01:00
'php_version' => '8.0' ,
2021-03-22 14:08:05 +01:00
],
2020-10-03 03:09:37 +02:00
'noNamedArgsMethod' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-03 03:09:37 +02:00
class CustomerData
{
/** @no-named-arguments */
public function __construct (
public string $name ,
public string $email ,
public int $age ,
) {}
}
/**
2022-11-12 02:14:21 +01:00
* @ param array { age : int , name : string , email : string } $input
2020-10-03 03:09:37 +02:00
*/
function foo ( array $input ) : CustomerData {
return new CustomerData (
age : $input [ " age " ],
name : $input [ " name " ],
email : $input [ " email " ],
);
} ' ,
2021-03-23 00:58:22 +01:00
'error_message' => 'NamedArgumentNotAllowed' ,
2020-10-03 03:09:37 +02:00
],
'noNamedArgsFunction' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-03 03:09:37 +02:00
/** @no-named-arguments */
function takesArguments ( string $name , int $age ) : void {}
takesArguments ( age : 5 , name : " hello " ); ' ,
2021-03-23 00:58:22 +01:00
'error_message' => 'NamedArgumentNotAllowed' ,
2020-10-03 03:09:37 +02:00
],
2020-10-15 00:51:15 +02:00
'arrayWithoutAllNamedParameters' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-15 00:51:15 +02:00
class User {
public function __construct (
public int $id ,
public string $name ,
public int $age
) {}
}
/**
2022-11-12 02:14:21 +01:00
* @ param array { id : int , name : string } $data
2020-10-15 00:51:15 +02:00
*/
function processUserDataInvalid ( array $data ) : User {
return new User ( ... $data );
} ' ,
'error_message' => 'MixedArgument' ,
2022-01-13 19:49:37 +01:00
'ignored_issues' => [],
2022-12-18 17:15:15 +01:00
'php_version' => '8.0' ,
2020-10-15 00:51:15 +02:00
],
'arrayWithoutAllNamedParametersSuppressMixed' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-10-15 00:51:15 +02:00
class User {
public function __construct (
public int $id ,
public string $name ,
public int $age
) {}
}
/**
2022-11-12 02:14:21 +01:00
* @ param array { id : int , name : string } $data
2020-10-15 00:51:15 +02:00
*/
function processUserDataInvalid ( array $data ) : User {
/** @psalm-suppress MixedArgument */
return new User ( ... $data );
} ' ,
'error_message' => 'TooFewArguments' ,
2022-01-13 19:49:37 +01:00
'ignored_issues' => [],
2022-12-18 17:15:15 +01:00
'php_version' => '8.0' ,
2020-10-15 00:51:15 +02:00
],
2020-11-16 21:49:27 +01:00
'wrongTypeVariadicArguments' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-11-16 21:49:27 +01:00
function takesArguments ( int ... $args ) : void {}
takesArguments ( age : " abc " ); ' ,
'error_message' => 'InvalidScalarArgument' ,
2022-01-13 19:49:37 +01:00
'ignored_issues' => [],
2022-12-18 17:15:15 +01:00
'php_version' => '8.0' ,
2020-11-16 21:49:27 +01:00
],
2020-12-14 22:57:48 +01:00
'byrefVarSetsPossible' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2020-12-14 22:57:48 +01:00
/**
* @ param mixed $a
* @ psalm - param - out int $a
*/
function takesByRef ( & $a ) : void {
$a = 5 ;
}
if ( rand ( 0 , 1 )) {
takesByRef ( $b );
}
echo $b ; ' ,
'error_message' => 'PossiblyUndefinedGlobalVariable' ,
],
2021-01-28 04:53:55 +01:00
'overwriteNamedParam' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-01-28 04:53:55 +01:00
function test ( int $param , int $param2 ) : void {
echo $param + $param2 ;
}
test ( param : 1 , param : 2 ); ' ,
'error_message' => 'InvalidNamedArgument' ,
2022-01-13 19:49:37 +01:00
'ignored_issues' => [],
2022-12-18 17:15:15 +01:00
'php_version' => '8.0' ,
2021-01-28 04:53:55 +01:00
],
'overwriteOrderedNamedParam' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-01-28 04:53:55 +01:00
function test ( int $param , int $param2 ) : void {
echo $param + $param2 ;
}
test ( 1 , param : 2 ); ' ,
'error_message' => 'InvalidNamedArgument' ,
2022-01-13 19:49:37 +01:00
'ignored_issues' => [],
2022-12-18 17:15:15 +01:00
'php_version' => '8.0' ,
2021-01-28 04:53:55 +01:00
],
2021-03-22 14:08:05 +01:00
'overwriteOrderedWithUnpackedNamedParam' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-03-22 14:08:05 +01:00
function test ( int $param , int $param2 ) : void {
echo $param + $param2 ;
}
test ( 1 , ... [ " param " => 2 ]); ' ,
'error_message' => 'InvalidNamedArgument' ,
2022-01-13 19:49:37 +01:00
'ignored_issues' => [],
2022-12-18 17:15:15 +01:00
'php_version' => '8.0' ,
2021-03-22 14:08:05 +01:00
],
2021-03-23 00:58:22 +01:00
'variadicArgumentIsNotList' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-03-23 00:58:22 +01:00
/** @psalm-return list<int> */
function foo ( int ... $values ) : array
{
return $values ;
}
' ,
2022-12-13 21:40:19 +01:00
'error_message' => 'LessSpecificReturnStatement' ,
2021-03-23 00:58:22 +01:00
],
'preventUnpackingPossiblyIterable' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-03-23 00:58:22 +01:00
function foo ( int $arg1 , int $arg2 ) : void {}
/** @var iterable<int, int>|object */
$test = [ 1 , 2 ];
foo ( ... $test );
' ,
2022-12-18 17:15:15 +01:00
'error_message' => 'PossiblyInvalidArgument' ,
2021-03-23 00:58:22 +01:00
],
'SKIPPED-preventUnpackingPossiblyArray' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-03-23 00:58:22 +01:00
function foo ( int $arg1 , int $arg2 ) : void {}
/** @var array<int, int>|object */
$test = [ 1 , 2 ];
foo ( ... $test );
' ,
2022-12-18 17:15:15 +01:00
'error_message' => 'PossiblyInvalidArgument' ,
2021-03-23 00:58:22 +01:00
],
'noNamedArguments' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-03-23 00:58:22 +01:00
/**
* @ psalm - suppress UnusedParam
* @ no - named - arguments
*/
function foo ( int $arg1 , int $arg2 ) : void {}
foo ( arg2 : 0 , arg1 : 1 );
' ,
'error_message' => 'NamedArgumentNotAllowed' ,
2022-01-13 19:49:37 +01:00
'ignored_issues' => [],
'php_version' => '8.0' ,
2021-03-23 00:58:22 +01:00
],
'noNamedArgumentsUnpackIterable' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-03-23 00:58:22 +01:00
/**
* @ psalm - suppress UnusedParam
* @ no - named - arguments
*/
function foo ( int $arg1 , int $arg2 ) : void {}
/** @var iterable<string, int> */
$test = [ " arg1 " => 1 , " arg2 " => 2 ];
foo ( ... $test );
' ,
'error_message' => 'NamedArgumentNotAllowed' ,
2022-01-13 19:49:37 +01:00
'ignored_issues' => [],
'php_version' => '8.0' ,
2021-03-23 00:58:22 +01:00
],
'variadicArgumentWithNoNamedArgumentsPreventsPassingArrayWithStringKey' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-03-23 00:58:22 +01:00
/**
* @ no - named - arguments
* @ psalm - return list < int >
*/
function foo ( int ... $values ) : array
{
return $values ;
}
foo ( ... [ " a " => 0 ]);
' ,
'error_message' => 'NamedArgumentNotAllowed' ,
],
'unpackNonArrayKeyIterable' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-03-23 00:58:22 +01:00
/** @psalm-suppress UnusedParam */
function foo ( string ... $args ) : void {}
/** @var Iterator<float, string> */
$test = null ;
foo ( ... $test );
' ,
'error_message' => 'InvalidArgument' ,
],
2021-04-01 05:16:21 +02:00
'numericStringIsNotNonFalsy' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-04-01 05:16:21 +02:00
/** @param non-falsy-string $arg */
function foo ( string $arg ) : string
{
return $arg ;
}
/** @return numeric-string */
function bar () : string
{
return " 0 " ;
}
foo ( bar ());
' ,
'error_message' => 'ArgumentTypeCoercion' ,
],
2021-04-04 06:00:31 +02:00
'objectIsNotObjectWithProperties' => [
2022-01-13 19:49:37 +01:00
'code' => ' < ? php
2021-04-04 06:00:31 +02:00
function makeObj () : object {
return ( object )[ " a " => 42 ];
}
/** @param object{hmm:float} $_o */
function takesObject ( $_o ) : void {}
takesObject ( makeObj ()); // expected: ArgumentTypeCoercion
' ,
'error_message' => 'ArgumentTypeCoercion' ,
],
2022-05-09 06:40:04 +02:00
'objectRedundantCast' => [
2022-05-28 21:05:17 +02:00
'code' => ' < ? php
2022-05-09 06:40:04 +02:00
function makeObj () : object {
return ( object )[ " a " => 42 ];
}
function takesObject ( object $_o ) : void {}
takesObject (( object ) makeObj ()); // expected: RedundantCast
' ,
'error_message' => 'RedundantCast' ,
],
2022-01-08 21:50:21 +01:00
'MissingMandatoryParamWithNamedParams' => [
2022-01-14 21:13:34 +01:00
'code' => ' < ? php
2022-01-08 21:50:21 +01:00
class User
{
public function __construct (
protected string $name ,
protected string $problematicOne ,
protected string $id = " " ,
){}
}
new User (
name : " John " ,
id : " asd " ,
);
' ,
'error_message' => 'TooFewArguments' ,
],
2022-11-05 22:34:42 +01:00
'SealedRefuseUnsealed' => [
'code' => ' < ? php
2022-11-12 02:14:21 +01:00
/** @param array{test: string} $a */
2022-11-05 22:34:42 +01:00
function a ( array $a ) : string {
return $a [ " test " ];
}
2022-11-12 02:14:21 +01:00
/** @var array{test: string, ...} */
2022-11-05 22:34:42 +01:00
$unsealed = [];
a ( $unsealed );
' ,
'error_message' => 'InvalidArgument' ,
],
'SealedRefuseSealedExtra' => [
'code' => ' < ? php
2022-11-12 02:14:21 +01:00
/** @param array{test: string} $a */
2022-11-05 22:34:42 +01:00
function a ( array $a ) : string {
return $a [ " test " ];
}
$sealedExtraKeys = [ " test " => " str " , " somethingElse " => " test " ];
a ( $sealedExtraKeys );
' ,
2022-11-26 17:26:36 +01:00
'error_message' => 'InvalidArgument - src' . DIRECTORY_SEPARATOR . 'somefile.php:8:23 - Argument 1 of a expects array{test: string}, but array{somethingElse: \'test\', test: \'str\'} with additional array shape fields (somethingElse) was provided' ,
2022-11-05 22:34:42 +01:00
],
2022-10-22 08:48:18 +02:00
'callbackArgsCountMismatch' => [
2022-11-08 10:25:04 +01:00
'code' => ' < ? php
2022-10-22 08:48:18 +02:00
/**
* @ param callable ( string , string ) : void $callback
* @ return void
*/
function caller ( $callback ) {}
/**
* @ param string $a
* @ return void
*/
function foo ( $a ) {}
caller ( " foo " ); ' ,
2023-04-19 11:56:04 +02:00
'error_message' => 'PossiblyInvalidArgument' ,
2022-10-22 08:48:18 +02:00
],
'callableArgsCountMismatch' => [
2022-11-08 10:25:04 +01:00
'code' => ' < ? php
2022-10-22 08:48:18 +02:00
/**
* @ param callable ( string ) : void $callback
* @ return void
*/
function caller ( $callback ) {}
/**
* @ param string $a
* @ param string $b
* @ return void
*/
function foo ( $a , $b ) {}
caller ( " foo " ); ' ,
2023-04-19 11:56:04 +02:00
'error_message' => 'InvalidArgument' ,
2022-10-22 08:48:18 +02:00
],
2017-04-08 15:28:02 +02:00
];
}
2016-12-09 18:07:47 +01:00
}