,error_levels?:string[]}> */ public function providerValidCodeParse() { return [ 'assertTemplatedType' => [ 'sayHello();', ], 'assertInstanceofTemplatedClassMethodUnknownClass' => [ ' $expected * @param mixed $actual * @psalm-assert T $actual */ public function assertInstanceOf($expected, $actual) : void {} /** * @param class-string $c */ function bar(string $c, object $e) : void { $this->assertInstanceOf($c, $e); echo $e->getCode(); } }', [], ['MixedArgument', 'MixedMethodCall'], ], 'assertInstanceofTemplatedClassMethodUnknownStringClass' => [ ' $expected * @param mixed $actual * @psalm-assert T $actual */ public function assertInstanceOf($expected, $actual) : void {} function bar(string $c, object $e) : void { $this->assertInstanceOf($c, $e); echo $e->getCode(); } }', [], ['MixedArgument', 'MixedMethodCall', 'ArgumentTypeCoercion'], ], 'assertInstanceofTemplatedFunctionUnknownClass' => [ ' $expected * @param mixed $actual * @psalm-assert T $actual */ function assertInstanceOf($expected, $actual) : void {} /** * @param class-string $c */ function bar(string $c, object $e) : void { assertInstanceOf($c, $e); echo $e->getCode(); }', [], ['MixedArgument', 'MixedMethodCall'], ], 'assertInstanceofTemplatedFunctionUnknownStringClass' => [ ' $expected * @param mixed $actual * @psalm-assert T $actual */ function assertInstanceOf($expected, $actual) : void {} function bar(string $c, object $e) : void { assertInstanceOf($c, $e); echo $e->getCode(); }', [], ['MixedArgument', 'MixedMethodCall', 'ArgumentTypeCoercion'], ], 'assertTypedArray' => [ ' $expected * @param mixed $actual * @psalm-assert T[] $actual */ function assertArrayOf($expected, $actual) : void {} function bar(array $arr) : void { assertArrayOf(A::class, $arr); foreach ($arr as $a) { $a->foo(); } }', ], 'assertTemplatedTypeString' => [ 'bat();', [ '$f' => 'Foo', ], ], 'suppressRedundantCondition' => [ ' [ ' [ ' [ ' [ ' [ ' $i * * @param iterable $i * @param class-string $type */ function assertAllInstanceOf(iterable $i, string $type): void { /** @psalm-suppress MixedAssignment */ foreach ($i as $elt) { if (!$elt instanceof $type) { throw new \UnexpectedValueException(""); } } } class A {} function getArray(): array { return []; } $array = getArray(); assertAllInstanceOf($array, A::class);', [ '$array' => 'array', ], ], 'assertAllIterableOfClass' => [ ' $i * * @param iterable $i * @param class-string $type */ function assertAllInstanceOf(iterable $i, string $type): void { /** @psalm-suppress MixedAssignment */ foreach ($i as $elt) { if (!$elt instanceof $type) { throw new \UnexpectedValueException(""); } } } class A {} function getIterable(): iterable { return []; } $iterable = getIterable(); assertAllInstanceOf($iterable, A::class);', [ '$iterable' => 'iterable', ], ], 'complicatedAssertAllInstanceOf' => [ ' $i * * @param iterable $i * @param class-string $type */ function allInstanceOf(iterable $i, string $type): bool { /** @psalm-suppress MixedAssignment */ foreach ($i as $elt) { if (!$elt instanceof $type) { return false; } } return true; } interface IBlogPost { public function getId(): int; } function getData(): iterable { return []; } $data = getData(); assert(allInstanceOf($data, IBlogPost::class)); foreach ($data as $post) { echo $post->getId(); }', ], 'assertUnionInNamespace' => [ ' $interface * @psalm-assert ExpectedType|class-string $value */ function implementsInterface($value, $interface, string $message = ""): void {} /** * @psalm-template ExpectedType of object * @param mixed $value * @psalm-param class-string $interface * @psalm-assert null|ExpectedType|class-string $value */ function nullOrImplementsInterface(?object $value, $interface, string $message = ""): void {} interface A { } /** * @param mixed $value * * @psalm-return A|class-string */ function consume($value) { implementsInterface($value, A::class); return $value; } /** * @param mixed $value * * @psalm-return A|class-string|null */ function consume2($value) { nullOrImplementsInterface($value, A::class); return $value; }' ], 'assertTemplatedTemplateSimple' => [ ' $c * * @return T2 */ function example(Clazz $c) { /** @var mixed */ $x = 0; $c->is($x); return $x; }' ], 'assertTemplatedTemplateIfTrue' => [ ' $c * * @return T2|false */ function example(Clazz $c) { /** @var mixed */ $x = 0; return $c->is($x) ? $x : false; }' ], ]; } /** * @return iterable */ public function providerInvalidCodeParse() { return [ 'detectRedundantCondition' => [ ' 'RedundantCondition', ], 'detectAssertSameTypeDoesNotContainType' => [ ' 'TypeDoesNotContainType', ], 'detectAssertAlwaysSame' => [ ' 'RedundantCondition', ], 'detectNeverCanBeSameAfterAssertion' => [ ' 'TypeDoesNotContainType', ], 'detectNeverCanBeNotSameAfterAssertion' => [ ' 'RedundantCondition', ], 'detectNeverCanBeEqualAfterAssertion' => [ ' 'TypeDoesNotContainType', ], 'detectIntFloatNeverCanBeEqualAfterAssertion' => [ ' 'TypeDoesNotContainType', ], 'detectFloatIntNeverCanBeEqualAfterAssertion' => [ ' 'TypeDoesNotContainType', ], 'assertNotSameDifferentTypes' => [ ' 'RedundantCondition', ], 'assertNotSameDifferentTypesExplicitString' => [ ' 'RedundantCondition', ], ]; } }