1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00
psalm/tests/TypeReconciliation/ScopeTest.php
orklah 005373bbc2
Detect redundant cast (#4695)
* detect redundant cast

* fix redundant cast issues

* fix redundant cast in tests
2021-01-29 11:46:25 +01:00

295 lines
9.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Psalm\Tests\TypeReconciliation;
use const DIRECTORY_SEPARATOR;
class ScopeTest extends \Psalm\Tests\TestCase
{
use \Psalm\Tests\Traits\InvalidCodeAnalysisTestTrait;
use \Psalm\Tests\Traits\ValidCodeAnalysisTestTrait;
/**
* @return iterable<string,array{string,assertions?:array<string,string>,error_levels?:string[]}>
*/
public function providerValidCodeParse(): iterable
{
return [
'newVarInIf' => [
'<?php
if (rand(0,100) === 10) {
$badge = "hello";
}
else {
$badge = "goodbye";
}
echo $badge;',
],
'newVarInIfWithElseReturn' => [
'<?php
if (rand(0,100) === 10) {
$badge = "hello";
}
else {
throw new \Exception();
}
echo $badge;',
],
'passByRefInVarWithBoolean' => [
'<?php
$a = preg_match("/bad/", "badger", $matches) > 0;
if ($a) {
echo $matches[1];
}',
],
'functionExists' => [
'<?php
if (true && function_exists("flabble")) {
flabble();
}',
],
'nestedPropertyFetchInElseif' => [
'<?php
class A {
/** @var A|null */
public $foo;
public function __toString(): string {
return "boop";
}
}
$a = rand(0, 10) === 5 ? new A(): null;
if (rand(0, 1)) {
} elseif ($a && $a->foo) {
echo $a;
}',
],
'globalReturn' => [
'<?php
$foo = "foo";
function a(): string {
global $foo;
return $foo;
}',
],
'globalReturnWithAnnotation' => [
'<?php
/**
* @global string $foo
*/
function a(): string {
global $foo;
return $foo;
}',
],
'negateAssertionAndOther' => [
'<?php
$a = rand(0, 10) ? "hello" : null;
if (rand(0, 10) > 1 && is_string($a)) {
throw new \Exception("bad");
}',
'assertions' => [
'$a' => 'null|string',
],
],
'repeatAssertionWithOther' => [
'<?php
function getString() : string {
return "hello";
}
$a = rand(0, 10) ? getString() : null;
if (rand(0, 10) > 1 || is_string($a)) {
if (is_string($a)) {
echo strpos($a, "e");
}
}',
'assertions' => [
'$a' => 'null|string',
],
'error_levels' => ['PossiblyFalseArgument'],
],
'refineOredType' => [
'<?php
class A {
public function doThing(): void
{
if ($this instanceof B || $this instanceof C) {
if ($this instanceof B) {
}
}
}
}
class B extends A {}
class C extends A {}',
],
'instanceOfSubtraction' => [
'<?php
class Foo {}
class FooBar extends Foo{}
class FooBarBat extends FooBar{}
class FooMoo extends Foo{}
$a = new Foo();
if ($a instanceof FooBar && !$a instanceof FooBarBat) {
} elseif ($a instanceof FooMoo) {
}',
],
'staticNullRef' => [
'<?php
/** @return void */
function foo() {
static $bar = null;
if ($bar !== null) {
// do something
}
$bar = 5;
}',
],
'suppressInvalidThis' => [
'<?php
/** @psalm-suppress InvalidScope */
if (!isset($this->value)) {
$this->value = ["x", "y"];
echo count($this->value) - 2;
}',
'assertions' => [],
'error_levels' => ['MixedPropertyAssignment', 'MixedArgument'],
],
'typedStatic' => [
'<?php
function a(): ?int {
/** @var ?int */
static $foo = 5;
if (rand(0, 1)) {
return $foo;
}
$foo = null;
return $foo;
}',
],
'psalmScopeThisInTemplate' => [
'<?php
$e = new Exception(); // necessary to trick Psalms scanner for test
/** @psalm-scope-this Exception */
?>
<h1><?= $this->getMessage() ?></h1>',
],
];
}
/**
* @return iterable<string,array{string,error_message:string,2?:string[],3?:bool,4?:string}>
*/
public function providerInvalidCodeParse(): iterable
{
return [
'possiblyUndefinedVarInIf' => [
'<?php
if (rand(0,100) === 10) {
$b = "s";
}
echo $b;',
'error_message' => 'PossiblyUndefinedGlobalVariable - src' . DIRECTORY_SEPARATOR . 'somefile.php:6:26 - Possibly undefined global '
. 'variable $b, first seen on line 3',
],
'possiblyUndefinedArrayInIf' => [
'<?php
if (rand(0,100) === 10) {
$array[] = "hello";
}
echo $array;',
'error_message' => 'PossiblyUndefinedGlobalVariable - src' . DIRECTORY_SEPARATOR . 'somefile.php:3:25 - Possibly undefined global '
. 'variable $array, first seen on line 3',
],
'invalidGlobal' => [
'<?php
$a = "heli";
global $a;',
'error_message' => 'InvalidGlobal',
],
'thisInStatic' => [
'<?php
class A {
public static function fooFoo() {
echo $this;
}
}',
'error_message' => 'InvalidScope',
],
'static' => [
'<?php
function a(): string {
static $foo = "foo";
return $foo;
}',
'error_message' => 'MixedReturnStatement',
],
'staticNullRef' => [
'<?php
/** @return void */
function foo() {
/** @var int */
static $bar = 5;
if ($bar === null) {
// do something
}
$bar = 4;
}',
'error_message' => 'DocblockTypeContradiction',
],
'typedStaticCannotHaveNullDefault' => [
'<?php
function a(): void {
/** @var string */
static $foo = null;
}',
'error_message' => 'ReferenceConstraintViolation',
],
'typedStaticCannotBeAssignedInt' => [
'<?php
function a(): void {
/** @var string */
static $foo = "foo";
$foo = 5;
}',
'error_message' => 'ReferenceConstraintViolation',
],
'typedStaticCannotBeAssignedNull' => [
'<?php
function a(): void {
/** @var string */
static $foo = "foo";
$foo = null;
}',
'error_message' => 'ReferenceConstraintViolation',
],
];
}
}