Skip to content

Commit

Permalink
Regression tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jan 12, 2022
1 parent 12b6bf7 commit ebfe7cf
Show file tree
Hide file tree
Showing 14 changed files with 240 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Analyser/NodeScopeResolver.php
Expand Up @@ -982,6 +982,7 @@ private function processStmtNode(
foreach ($stmt->cond as $condExpr) {
$condResult = $this->processExprNode($condExpr, $bodyScope, static function (): void {
}, ExpressionContext::createDeep());
$initScope = $condResult->getScope();
$condTruthiness = $condResult->getScope()->getType($condExpr)->toBoolean();
if ($condTruthiness instanceof ConstantBooleanType) {
$condTruthinessTrinary = TrinaryLogic::createFromBoolean($condTruthiness->getValue());
Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Expand Up @@ -597,6 +597,11 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/pdo-prepare.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/constant-array-type-set.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/for-loop-i-type.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5316.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-3858.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2806.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5328.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-3044.php');
}

/**
Expand Down
15 changes: 15 additions & 0 deletions tests/PHPStan/Analyser/data/bug-2806.php
@@ -0,0 +1,15 @@
<?php

namespace Bug2806;

use PHPStan\TrinaryLogic;
use function PHPStan\Testing\assertVariableCertainty;

function (): void {
for (;;) {
$a = "hello";
break;
}

assertVariableCertainty(TrinaryLogic::createYes(), $a);
};
42 changes: 42 additions & 0 deletions tests/PHPStan/Analyser/data/bug-3044.php
@@ -0,0 +1,42 @@
<?php

namespace Bug3044;

use function PHPStan\Testing\assertType;

class HelloWorld
{
/**
* @return array<int, array<int, float>>
*/
private function getIntArrayFloatArray(): array
{
return [
0 => [1.1, 2.2, 3.3],
1 => [1.1, 2.2, 3.3],
2 => [1.1, 2.2, 3.3],
];
}

/**
* @return array<int, array<int, float>>
*/
public function invalidType(): void
{
$X = $this->getIntArrayFloatArray();
$L = $this->getIntArrayFloatArray();

$n = 3;
$m = 3;

for ($k = 0; $k < $m; ++$k) {
for ($j = 0; $j < $n; ++$j) {
for ($i = 0; $i < $k; ++$i) {
$X[$k][$j] -= $X[$i][$j] * $L[$k][$i];
}
}
}

assertType('array<int, array<int, float>>', $X);
}
}
25 changes: 25 additions & 0 deletions tests/PHPStan/Analyser/data/bug-3858.php
@@ -0,0 +1,25 @@
<?php

namespace Bug3858;

use PHPStan\TrinaryLogic;
use function PHPStan\Testing\assertVariableCertainty;

class BinarySearch
{
/**
* @param mixed[] $items
*/
public function __invoke(array $items): void
{
for ($start = 0, $end = count($items);
$i = $start + (int) (($end - $start) / 2), $i < $end;
) {
// do something here, then break at some point
break;
}

// $i is always defined here, even with an empty array
assertVariableCertainty(TrinaryLogic::createYes(), $i);
}
}
25 changes: 25 additions & 0 deletions tests/PHPStan/Analyser/data/bug-5316.php
@@ -0,0 +1,25 @@
<?php

namespace Bug5316;

use function PHPStan\Testing\assertType;

function (): void {
$map = [
1 => 'foo',
2 => 'foo',
3 => 'bar',
];
$names = ['foo', 'bar', 'baz'];
$array = ['foo' => [], 'bar' => [], 'baz' => []];

foreach ($map as $value => $name) {
$array[$name][] = $value;
}


foreach ($array as $name => $elements) {
assertType('bool', count($elements) > 0);
assertType('array<int, 1|2|3>', $elements);
}
};
25 changes: 25 additions & 0 deletions tests/PHPStan/Analyser/data/bug-5328.php
@@ -0,0 +1,25 @@
<?php

namespace Bug5328;

use function PHPStan\Testing\assertType;

class Foo
{

function produceIntOrNull(): ?int
{
return rand(0, 2) === 0 ? null : 0;
}

function doBar()
{
$int = $this->produceIntOrNull();
for ($i = 0; $i < 5 && !is_int($int) ; $i++) {
$int = $this->produceIntOrNull();
}

assertType('int|null', $int);
}

}
Expand Up @@ -441,4 +441,11 @@ public function testArrayIsList(): void
]);
}

public function testBug3766(): void
{
$this->checkAlwaysTrueCheckTypeFunctionCall = true;
$this->treatPhpDocTypesAsCertain = true;
$this->analyse([__DIR__ . '/data/bug-3766.php'], []);
}

}
Expand Up @@ -53,4 +53,14 @@ public function testBug5161(): void
$this->analyse([__DIR__ . '/data/bug-5161.php'], []);
}

public function testBug3310(): void
{
$this->analyse([__DIR__ . '/data/bug-3310.php'], []);
}

public function testBug3264(): void
{
$this->analyse([__DIR__ . '/data/bug-3264.php'], []);
}

}
17 changes: 17 additions & 0 deletions tests/PHPStan/Rules/Comparison/data/bug-3264.php
@@ -0,0 +1,17 @@
<?php

namespace Bug3264;

function (): void {
$totalShops = 40;
$predefinedShops = 10;

for ($i = 0; $i < $predefinedShops; $i++)
{
echo "Do something $i...\n";
}
for (;$i < $totalShops; $i++)
{
echo "Do something else $i...\n";
}
};
11 changes: 11 additions & 0 deletions tests/PHPStan/Rules/Comparison/data/bug-3310.php
@@ -0,0 +1,11 @@
<?php

namespace Bug3310;

function explain(int $bitField): void
{
for ($i = 0; $i < 5; ++$i) {
}
for (; $i < 15; ++$i) {
}
}
28 changes: 28 additions & 0 deletions tests/PHPStan/Rules/Comparison/data/bug-3766.php
@@ -0,0 +1,28 @@
<?php

namespace Bug3766;

class Foo
{

/**
* @return array<mixed>
*/
function get_foo(): array
{
return [];
}

public function doFoo(): void
{
$foo = $this->get_foo();
for ($i = 0; $i < \count($foo); $i++) {
if (\array_key_exists($i + 1, $foo)
&& \array_key_exists($i + 2, $foo)
) {
echo $i;
}
}
}

}
Expand Up @@ -48,4 +48,14 @@ public function testDefaultValueForNativePropertyType(): void
]);
}

public function testBug5607(): void
{
$this->analyse([__DIR__ . '/data/bug-5607.php'], [
[
'Property Bug5607\Cl::$u (Bug5607\A|null) does not accept default value of type array<int|string, string>.',
10,
],
]);
}

}
19 changes: 19 additions & 0 deletions tests/PHPStan/Rules/Properties/data/bug-5607.php
@@ -0,0 +1,19 @@
<?php

namespace Bug5607;

class A {}

class Cl
{
/** @var A|null */
public $u = [A::class, 'ui' => 'basic segment'];

/**
* @param array<int|string, class-string|string> $x
*/
public function mm($x): void
{
throw new \Exception();
}
}

0 comments on commit ebfe7cf

Please sign in to comment.