mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 05:41:20 +01:00
Fix errors in doctrine/dbal
This commit is contained in:
parent
72c50be4b0
commit
c3a1e77a53
@ -152,6 +152,7 @@ class ArrayFetchAnalyzer
|
||||
if ($context->inside_isset
|
||||
&& $stmt->dim
|
||||
&& isset($stmt->dim->inferredType)
|
||||
&& $stmt->var->inferredType->hasArray()
|
||||
&& ($stmt->var instanceof PhpParser\Node\Expr\ClassConstFetch
|
||||
|| $stmt->var instanceof PhpParser\Node\Expr\ConstFetch)
|
||||
) {
|
||||
@ -649,9 +650,7 @@ class ArrayFetchAnalyzer
|
||||
)) {
|
||||
$expected_offset_types[] = $valid_offset_type->getId();
|
||||
|
||||
if (!$inside_isset) {
|
||||
$array_access_type = Type::getMixed();
|
||||
}
|
||||
} else {
|
||||
$has_valid_offset = true;
|
||||
|
||||
|
@ -487,6 +487,24 @@ class IssetTest extends TestCase
|
||||
'assertions' => [],
|
||||
'error_levels' => ['MixedAssignment'],
|
||||
],
|
||||
'noCrashAfterIsset' => [
|
||||
'<?php
|
||||
/**
|
||||
* @param string[] $columns
|
||||
* @param mixed[] $options
|
||||
*/
|
||||
function foo(array $columns, array $options) : void {
|
||||
$arr = $options["b"];
|
||||
|
||||
foreach ($arr as $a) {
|
||||
if (isset($columns[$a]["c"])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'error_levels' => ['MixedAssignment', 'MixedArrayOffset', 'InvalidArrayOffset'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
217
tests/TypeAnnotationTest.php
Normal file
217
tests/TypeAnnotationTest.php
Normal file
@ -0,0 +1,217 @@
|
||||
<?php
|
||||
namespace Psalm\Tests;
|
||||
|
||||
use Psalm\Config;
|
||||
use Psalm\Context;
|
||||
|
||||
class TypeAnnotationTest extends TestCase
|
||||
{
|
||||
use Traits\InvalidCodeAnalysisTestTrait;
|
||||
use Traits\ValidCodeAnalysisTestTrait;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function providerValidCodeParse()
|
||||
{
|
||||
return [
|
||||
'typeAliasBeforeClass' => [
|
||||
'<?php
|
||||
/**
|
||||
* @psalm-type CoolType = A|B|null
|
||||
*/
|
||||
|
||||
class A {}
|
||||
class B {}
|
||||
|
||||
/** @return CoolType */
|
||||
function foo() {
|
||||
if (rand(0, 1)) {
|
||||
return new A();
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
return new B();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @param CoolType $a **/
|
||||
function bar ($a) : void { }
|
||||
|
||||
bar(foo());'
|
||||
],
|
||||
'typeAliasBeforeFunction' => [
|
||||
'<?php
|
||||
/**
|
||||
* @psalm-type A_OR_B = A|B
|
||||
* @psalm-type CoolType = A_OR_B|null
|
||||
* @return CoolType
|
||||
*/
|
||||
function foo() {
|
||||
if (rand(0, 1)) {
|
||||
return new A();
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
return new B();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
class A {}
|
||||
class B {}
|
||||
|
||||
/** @param CoolType $a **/
|
||||
function bar ($a) : void { }
|
||||
|
||||
bar(foo());'
|
||||
],
|
||||
'typeAliasInSeparateBlockBeforeFunction' => [
|
||||
'<?php
|
||||
/**
|
||||
* @psalm-type CoolType = A|B|null
|
||||
*/
|
||||
/**
|
||||
* @return CoolType
|
||||
*/
|
||||
function foo() {
|
||||
if (rand(0, 1)) {
|
||||
return new A();
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
return new B();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
class A {}
|
||||
class B {}
|
||||
|
||||
/** @param CoolType $a **/
|
||||
function bar ($a) : void { }
|
||||
|
||||
bar(foo());'
|
||||
],
|
||||
'almostFreeStandingTypeAlias' => [
|
||||
'<?php
|
||||
/**
|
||||
* @psalm-type CoolType = A|B|null
|
||||
*/
|
||||
|
||||
// this breaks up the line
|
||||
|
||||
class A {}
|
||||
class B {}
|
||||
|
||||
/** @return CoolType */
|
||||
function foo() {
|
||||
if (rand(0, 1)) {
|
||||
return new A();
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
return new B();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @param CoolType $a **/
|
||||
function bar ($a) : void { }
|
||||
|
||||
bar(foo());'
|
||||
],
|
||||
'typeAliasUsedTwice' => [
|
||||
'<?php
|
||||
/** @psalm-type TA = array<int, string> */
|
||||
|
||||
class Bar {
|
||||
public function foo() : void {
|
||||
$bar =
|
||||
/** @return TA */
|
||||
function() {
|
||||
return ["hello"];
|
||||
};
|
||||
|
||||
/** @var array<int, TA> */
|
||||
$bat = [$bar(), $bar()];
|
||||
|
||||
foreach ($bat as $b) {
|
||||
echo $b[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-type _A=array{elt:int}
|
||||
* @param _A $p
|
||||
* @return _A
|
||||
*/
|
||||
function f($p) {
|
||||
/** @var _A */
|
||||
$r = $p;
|
||||
return $r;
|
||||
}',
|
||||
],
|
||||
'namespacedType' => [
|
||||
'<?php
|
||||
namespace Foo {
|
||||
class A {
|
||||
/**
|
||||
* @psalm-type self::TBaz = A|\Bar\B
|
||||
*/
|
||||
public function foo() : void {}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Bar {
|
||||
class B {
|
||||
/**
|
||||
* @param \Foo\A::TBaz $a
|
||||
*/
|
||||
public function tender($a) : void {
|
||||
$a->foo();
|
||||
}
|
||||
|
||||
public function foo() : void {}
|
||||
}
|
||||
}'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function providerInvalidCodeParse()
|
||||
{
|
||||
return [
|
||||
'invalidTypeAlias' => [
|
||||
'<?php
|
||||
/**
|
||||
* @psalm-type CoolType = A|B>
|
||||
*/
|
||||
|
||||
class A {}',
|
||||
'error_message' => 'InvalidDocblock',
|
||||
],
|
||||
'typeAliasInObjectLike' => [
|
||||
'<?php
|
||||
/**
|
||||
* @psalm-type aType null|"a"|"b"|"c"|"d"
|
||||
*/
|
||||
|
||||
/** @psalm-return array{0:bool,1:aType} */
|
||||
function f(): array {
|
||||
return [(bool)rand(0,1), rand(0,1) ? "z" : null];
|
||||
}',
|
||||
'error_message' => 'InvalidReturnStatement',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user