Skip to content
14 changes: 14 additions & 0 deletions src/Analyser/ExpressionResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace PHPStan\Analyser;

use PHPStan\Type\Type;

final class ExpressionResult
{

Expand Down Expand Up @@ -29,12 +31,24 @@ public function __construct(
private array $impurePoints,
?callable $truthyScopeCallback = null,
?callable $falseyScopeCallback = null,
private ?Type $type = null,
private ?Type $nativeType = null,
)
{
$this->truthyScopeCallback = $truthyScopeCallback;
$this->falseyScopeCallback = $falseyScopeCallback;
}

public function getType(): ?Type
{
return $this->type;
}

public function getNativeType(): ?Type
{
return $this->nativeType;
}

public function getScope(): MutatingScope
{
return $this->scope;
Expand Down
36 changes: 36 additions & 0 deletions src/Analyser/ExpressionResultStorage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

use PhpParser\Node\Expr;
use SplObjectStorage;

final class ExpressionResultStorage
{

/** @var SplObjectStorage<Expr, ExpressionResult> */
private SplObjectStorage $results;

public function __construct()
{
$this->results = new SplObjectStorage();
}

public function duplicate(): self
{
$new = new self();
$new->results->addAll($this->results);
return $new;
}

public function storeResult(Expr $expr, ExpressionResult $result): void
{
$this->results[$expr] = $result;
}

public function findResult(Expr $expr): ?ExpressionResult
{
return $this->results[$expr] ?? null;
}

}
21 changes: 12 additions & 9 deletions src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -982,9 +982,7 @@ private function resolveType(string $exprString, Expr $node): Type
}

if ($this->getBooleanExpressionDepth($node->left) <= self::BOOLEAN_EXPRESSION_MAX_PROCESS_DEPTH) {
$noopCallback = static function (): void {
};
$leftResult = $this->nodeScopeResolver->processExprNode(new Node\Stmt\Expression($node->left), $node->left, $this, $noopCallback, ExpressionContext::createDeep());
$leftResult = $this->nodeScopeResolver->processExprNode(new Node\Stmt\Expression($node->left), $node->left, $this, new ExpressionResultStorage(), new NoopNodeCallback(), ExpressionContext::createDeep());
$rightBooleanType = $leftResult->getTruthyScope()->getType($node->right)->toBoolean();
} else {
$rightBooleanType = $this->filterByTruthyValue($node->left)->getType($node->right)->toBoolean();
Expand Down Expand Up @@ -1014,9 +1012,7 @@ private function resolveType(string $exprString, Expr $node): Type
}

if ($this->getBooleanExpressionDepth($node->left) <= self::BOOLEAN_EXPRESSION_MAX_PROCESS_DEPTH) {
$noopCallback = static function (): void {
};
$leftResult = $this->nodeScopeResolver->processExprNode(new Node\Stmt\Expression($node->left), $node->left, $this, $noopCallback, ExpressionContext::createDeep());
$leftResult = $this->nodeScopeResolver->processExprNode(new Node\Stmt\Expression($node->left), $node->left, $this, new ExpressionResultStorage(), new NoopNodeCallback(), ExpressionContext::createDeep());
$rightBooleanType = $leftResult->getFalseyScope()->getType($node->right)->toBoolean();
} else {
$rightBooleanType = $this->filterByFalseyValue($node->left)->getType($node->right)->toBoolean();
Expand Down Expand Up @@ -1406,6 +1402,7 @@ private function resolveType(string $exprString, Expr $node): Type
new Node\Stmt\Expression($node->expr),
$node->expr,
$arrowScope,
new ExpressionResultStorage(),
static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpurePoints, &$invalidateExpressions): void {
if ($scope->getAnonymousFunctionReflection() !== $arrowScope->getAnonymousFunctionReflection()) {
return;
Expand Down Expand Up @@ -2042,9 +2039,7 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu
}

if ($node instanceof Expr\Ternary) {
$noopCallback = static function (): void {
};
$condResult = $this->nodeScopeResolver->processExprNode(new Node\Stmt\Expression($node->cond), $node->cond, $this, $noopCallback, ExpressionContext::createDeep());
$condResult = $this->nodeScopeResolver->processExprNode(new Node\Stmt\Expression($node->cond), $node->cond, $this, new ExpressionResultStorage(), new NoopNodeCallback(), ExpressionContext::createDeep());
if ($node->if === null) {
$conditionType = $this->getType($node->cond);
$booleanConditionType = $conditionType->toBoolean();
Expand Down Expand Up @@ -5752,6 +5747,14 @@ public function debug(): array
$descriptions[$key] = $nativeTypeHolder->getType()->describe(VerbosityLevel::precise());
}

foreach (array_keys($this->currentlyAssignedExpressions) as $exprString) {
$descriptions[sprintf('currently assigned %s', $exprString)] = 'true';
}

foreach (array_keys($this->currentlyAllowedUndefinedExpressions) as $exprString) {
$descriptions[sprintf('currently allowed undefined %s', $exprString)] = 'true';
}

foreach ($this->conditionalExpressions as $exprString => $holders) {
foreach (array_values($holders) as $i => $holder) {
$key = sprintf('condition about %s #%d', $exprString, $i + 1);
Expand Down
Loading
Loading