1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00
psalm/tests/Php71Test.php
Matthew Brown b0733254bb
Use individual type objects for each string (#757)
* Experiment with individual types for each string

* Fix bunch of errors

* Fix a few more issues

* Fix a whole bunch of bugs

* Fix most remaining bugs

* Fix isset warnings

* Fix psalm errors in psalm

* Limit big string size

* Fix falsiness of ints

* Fix issue with type widening, allowing value set in nested if to be altered

* Don’t complain if type is mixed

* Add skipped-for-now test

* Add specific test to address issue
2018-05-18 11:02:50 -04:00

299 lines
9.2 KiB
PHP

<?php
namespace Psalm\Tests;
class Php71Test extends TestCase
{
use Traits\FileCheckerInvalidCodeParseTestTrait;
use Traits\FileCheckerValidCodeParseTestTrait;
/**
* @return array
*/
public function providerFileCheckerValidCodeParse()
{
return [
'nullableReturnType' => [
'<?php
function a(): ?string
{
return rand(0, 10) ? "elePHPant" : null;
}
$a = a();',
'assertions' => [
'$a' => 'string|null',
],
],
'nullableReturnTypeInDocblock' => [
'<?php
/** @return ?string */
function a() {
return rand(0, 10) ? "elePHPant" : null;
}
$a = a();',
'assertions' => [
'$a' => 'null|string',
],
],
'nullableArgument' => [
'<?php
function test(?string $name): ?string
{
return $name;
}
test("elePHPant");
test(null);',
],
'protectedClassConst' => [
'<?php
class A
{
protected const IS_PROTECTED = 1;
}
class B extends A
{
function fooFoo(): int {
return A::IS_PROTECTED;
}
}',
],
'privateClassConst' => [
'<?php
class A
{
private const IS_PRIVATE = 1;
function fooFoo(): int {
return A::IS_PRIVATE;
}
}',
],
'publicClassConstFetch' => [
'<?php
class A
{
public const IS_PUBLIC = 1;
const IS_ALSO_PUBLIC = 2;
}
class B extends A
{
function fooFoo(): int {
echo A::IS_PUBLIC;
return A::IS_ALSO_PUBLIC;
}
}
echo A::IS_PUBLIC;
echo A::IS_ALSO_PUBLIC;',
],
'arrayDestructuring' => [
'<?php
$data = [
[1, "Tom"],
[2, "Fred"],
];
// list() style
list($id1, $name1) = $data[0];
// [] style
[$id2, $name2] = $data[1];',
'assertions' => [
'$id1' => 'int',
'$name1' => 'string',
'$id2' => 'int',
'$name2' => 'string',
],
],
'arrayDestructuringInForeach' => [
'<?php
$data = [
[1, "Tom"],
[2, "Fred"],
];
// [] style
foreach ($data as [$id, $name]) {
echo $id;
echo $name;
}',
],
'arrayDestructuringWithKeys' => [
'<?php
$data = [
["id" => 1, "name" => "Tom"],
["id" => 2, "name" => "Fred"],
];
// list() style
list("id" => $id1, "name" => $name1) = $data[0];
// [] style
["id" => $id2, "name" => $name2] = $data[1];',
'assertions' => [
'$id1' => 'int',
'$name1' => 'string',
'$id2' => 'int',
'$name2' => 'string',
],
],
'arrayListDestructuringInForeachWithKeys' => [
'<?php
$data = [
["id" => 1, "name" => "Tom"],
["id" => 2, "name" => "Fred"],
];
$last_id = null;
$last_name = null;
// list() style
foreach ($data as list("id" => $id, "name" => $name)) {
$last_id = $id;
$last_name = $name;
}',
'assertions' => [
'$last_id' => 'int|null',
'$last_name' => 'string|null',
],
],
'arrayDestructuringInForeachWithKeys' => [
'<?php
$data = [
["id" => 1, "name" => "Tom"],
["id" => 2, "name" => "Fred"],
];
$last_id = null;
$last_name = null;
// [] style
foreach ($data as ["id" => $id, "name" => $name]) {
$last_id = $id;
$last_name = $name;
}',
'assertions' => [
'$last_id' => 'int|null',
'$last_name' => 'string|null',
],
],
'iterableArg' => [
'<?php
/**
* @param iterable<int, int> $iter
*/
function iterator(iterable $iter): void
{
foreach ($iter as $val) {
//
}
}
iterator([1, 2, 3, 4]);
iterator(new SplFixedArray(5));',
],
'traversableObject' => [
'<?php
class IteratorObj implements Iterator {
function rewind(): void {}
/** @return mixed */
function current() { return null; }
function key(): int { return 0; }
function next(): void {}
function valid(): bool { return false; }
}
function foo(\Traversable $t): void {
}
foo(new IteratorObj);',
],
'iterableIsArrayOrTraversable' => [
'<?php
function castToArray(iterable $arr): array {
return $arr instanceof \Traversable ? iterator_to_array($arr, false) : $arr;
}
function castToArray2(iterable $arr): array {
return is_array($arr) ? $arr : iterator_to_array($arr, false);
}',
],
'substituteIterable' => [
'<?php
function foo(iterable $i): array {
if (!is_array($i)) {
$i = iterator_to_array($i, false);
}
return $i;
}',
],
];
}
/**
* @return array
*/
public function providerFileCheckerInvalidCodeParse()
{
return [
'invalidPrivateClassConstFetch' => [
'<?php
class A
{
private const IS_PRIVATE = 1;
}
echo A::IS_PRIVATE;',
'error_message' => 'InaccessibleClassConstant',
],
'invalidPrivateClassConstFetchFromSubclass' => [
'<?php
class A
{
private const IS_PRIVATE = 1;
}
class B extends A
{
function fooFoo(): int {
return A::IS_PRIVATE;
}
}',
'error_message' => 'InaccessibleClassConstant',
],
'invalidProtectedClassConstFetch' => [
'<?php
class A
{
protected const IS_PROTECTED = 1;
}
echo A::IS_PROTECTED;',
'error_message' => 'InaccessibleClassConstant',
],
'invalidIterableArg' => [
'<?php
/**
* @param iterable<string> $iter
*/
function iterator(iterable $iter): void
{
foreach ($iter as $val) {
//
}
}
class A {
}
iterator(new A());',
'error_message' => 'InvalidArgument',
],
];
}
}