Skip to content

Commit b7f8925

Browse files
committed
Added ExpressionResultTest
1 parent 5e5878f commit b7f8925

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

src/Analyser/NodeScopeResolver.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3199,6 +3199,7 @@ static function (): void {
31993199
$impurePoints = [
32003200
new ImpurePoint($scope, $expr, $identifier, $identifier, true),
32013201
];
3202+
$isAlwaysTerminating = true;
32023203
if ($expr->expr !== null) {
32033204
$result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep());
32043205
$hasYield = $result->hasYield();
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser;
4+
5+
use PhpParser\Node\Stmt;
6+
use PHPStan\Parser\Parser;
7+
use PHPStan\ShouldNotHappenException;
8+
use PHPStan\Testing\PHPStanTestCase;
9+
use PHPStan\TrinaryLogic;
10+
use PHPStan\Type\ArrayType;
11+
use PHPStan\Type\IntegerType;
12+
use PHPStan\Type\MixedType;
13+
use PHPStan\Type\StringType;
14+
use PHPUnit\Framework\Attributes\DataProvider;
15+
use function count;
16+
use function get_class;
17+
use function sprintf;
18+
19+
class ExpressionResultTest extends PHPStanTestCase
20+
{
21+
22+
public static function dataIsAlwaysTerminating(): array
23+
{
24+
return [
25+
[
26+
'sprintf("hello %s", "abc");',
27+
false,
28+
],
29+
[
30+
'sprintf("hello %s", exit());',
31+
true,
32+
],
33+
];
34+
}
35+
36+
#[DataProvider('dataIsAlwaysTerminating')]
37+
public function testIsAlwaysTerminating(
38+
string $code,
39+
bool $expectedIsAlwaysTerminating,
40+
): void
41+
{
42+
/** @var Parser $parser */
43+
$parser = self::getContainer()->getService('currentPhpVersionRichParser');
44+
45+
/** @var Stmt[] $stmts */
46+
$stmts = $parser->parseString(sprintf('<?php %s', $code));
47+
if (count($stmts) !== 1) {
48+
throw new ShouldNotHappenException('Expecting code which evaluates to a single statement, got: ' . count($stmts));
49+
}
50+
if (!$stmts[0] instanceof Stmt\Expression) {
51+
throw new ShouldNotHappenException('Expecting code contains a single statement expression, got: ' . get_class($stmts[0]));
52+
}
53+
$stmt = $stmts[0];
54+
$expr = $stmt->expr;
55+
56+
/** @var NodeScopeResolver $nodeScopeResolver */
57+
$nodeScopeResolver = self::getContainer()->getByType(NodeScopeResolver::class);
58+
/** @var ScopeFactory $scopeFactory */
59+
$scopeFactory = self::getContainer()->getByType(ScopeFactory::class);
60+
$scope = $scopeFactory->create(ScopeContext::create('test.php'))
61+
->assignVariable('string', new StringType(), new StringType(), TrinaryLogic::createYes())
62+
->assignVariable('x', new IntegerType(), new IntegerType(), TrinaryLogic::createYes())
63+
->assignVariable('cond', new MixedType(), new MixedType(), TrinaryLogic::createYes())
64+
->assignVariable('arr', new ArrayType(new MixedType(), new MixedType()), new ArrayType(new MixedType(), new MixedType()), TrinaryLogic::createYes());
65+
66+
$result = $nodeScopeResolver->processExprNode(
67+
$stmt,
68+
$expr,
69+
$scope,
70+
static function (): void {
71+
},
72+
ExpressionContext::createTopLevel(),
73+
);
74+
$this->assertSame($expectedIsAlwaysTerminating, $result->isAlwaysTerminating());
75+
}
76+
77+
}

0 commit comments

Comments
 (0)