,error_levels?:string[]}> */ public function providerValidCodeParse() { return [ 'assertInstanceOfB' => [ 'foo(); }', ], 'dropInReplacementForAssert' => [ ' [ 'bar(); $a->foo(); }', ], 'assertInstanceOfMultipleInterfaces' => [ 'bar(); $a->foo1(); }', ], 'assertInstanceOfBInClassMethod' => [ 'assertInstanceOfB($a); $a->foo(); } }', ], 'assertPropertyNotNull' => [ 'a) { throw new \Exception(); } } public function takesA(A $a): void { $this->assertNotNullProperty(); $a->foo(); } }', ], 'assertWithoutRedundantCondition' => [ ' [ 'foo(); }', ], 'assertIfTrueAnnotation' => [ ' [ ' [ ' [ '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'], ], 'assertTemplatedTypeString' => [ 'bat();', [ '$f' => 'Foo', ], ], 'dontBleedBadAssertVarIntoContext' => [ 'foo()); assertFalse($a->bar()); }', ], 'suppressRedundantCondition' => [ ' [ ' [ ' [ ' [ ' $i * * @param iterable $i */ function assertAllStrings(iterable $i): void { /** @psalm-suppress MixedAssignment */ foreach ($i as $s) { if (!is_string($s)) { throw new \UnexpectedValueException(""); } } } function getArray(): array { return []; } function getIterable(): iterable { return []; } $array = getArray(); assertAllStrings($array); $iterable = getIterable(); assertAllStrings($iterable);', [ '$array' => 'array', '$iterable' => 'iterable', ], ], 'assertAllArrayOfClass' => [ ' $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(); }', ], 'assertArrayReturnTypeNarrowed' => [ ' [ ' [ ' [ 'format("Y-m-d"); } }', ], 'assertCheckOnNonZeroArrayOffset' => [ ' [ ' $arr */ function uriToPath(array $arr) : string { if (!isset($arr["a"]) || $arr["b"] !== "foo") { throw new \InvalidArgumentException("bad"); } return (string) $arr["c"]; }', ], 'combineAfterLoopAssert' => [ ' [ ' [ ' [ ' [ ' [ ' [ ' [ ' [ 'bar();', ], ]; } /** * @return iterable */ public function providerInvalidCodeParse() { return [ 'assertInstanceOfMultipleInterfaces' => [ 'bar(); $a->foo1(); }', 'error_message' => 'UndefinedMethod', ], 'assertIfTrueNoAnnotation' => [ ' 'PossiblyNullOperand', ], 'assertIfFalseNoAnnotation' => [ ' 'PossiblyNullOperand', ], 'assertIfTrueMethodCall' => [ 'isInt($p)) { strlen($p); } } }', 'error_message' => 'InvalidScalarArgument', ], 'assertIfStaticTrueMethodCall' => [ 'isInt($p)) { strlen($p); } } }', 'error_message' => 'InvalidScalarArgument', ], 'noFatalForUnknownAssertClass' => [ 'sayHello();', 'error_message' => 'UndefinedDocblockClass', ], 'detectRedundantCondition' => [ ' 'RedundantCondition', ], 'detectAssertSameTypeDoesNotContainType' => [ ' 'TypeDoesNotContainType', ], 'detectAssertAlwaysSame' => [ ' 'RedundantCondition', ], 'detectNeverCanBeSameAfterAssertion' => [ ' 'TypeDoesNotContainType', ], 'detectNeverCanBeNotSameAfterAssertion' => [ ' 'RedundantCondition', ], 'detectNeverCanBeEqualAfterAssertion' => [ ' 'TypeDoesNotContainType', ], 'detectIntFloatNeverCanBeEqualAfterAssertion' => [ ' 'TypeDoesNotContainType', ], 'detectFloatIntNeverCanBeEqualAfterAssertion' => [ ' 'TypeDoesNotContainType', ], 'assertNotSameDifferentTypes' => [ ' 'RedundantCondition', ], 'assertNotSameDifferentTypesExplicitString' => [ ' 'RedundantCondition', ], 'assertValueImpossible' => [ ' 'InvalidDocblock', ], ]; } }