Skip to content

Commit

Permalink
NodeScopeResolver: refactor matching throw points computation
Browse files Browse the repository at this point in the history
  • Loading branch information
JanTvrdik authored and ondrejmirtes committed May 12, 2023
1 parent 87fe0f0 commit b206ea8
Showing 1 changed file with 42 additions and 40 deletions.
82 changes: 42 additions & 40 deletions src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -1267,61 +1267,63 @@ private function processStmtNode(
foreach ($stmt->catches as $catchNode) {
$nodeCallback($catchNode, $scope);

$catchType = TypeCombinator::union(...array_map(static fn (Name $name): Type => new ObjectType($name->toString()), $catchNode->types));
$originalCatchType = $catchType;
$isThrowable = TrinaryLogic::createNo()->lazyOr(
$originalCatchType->getObjectClassNames(),
static fn (string $objectClassName) => TrinaryLogic::createFromBoolean(strtolower($objectClassName) === 'throwable'),
);
$catchType = TypeCombinator::remove($catchType, $pastCatchTypes);
$originalCatchType = TypeCombinator::union(...array_map(static fn (Name $name): Type => new ObjectType($name->toString()), $catchNode->types));
$isThrowable = $originalCatchType->isSuperTypeOf(new ObjectType(Throwable::class))->yes();
$catchType = TypeCombinator::remove($originalCatchType, $pastCatchTypes);
$pastCatchTypes = TypeCombinator::union($pastCatchTypes, $originalCatchType);
$matchingThrowPoints = [];
$newThrowPoints = [];
foreach ($throwPoints as $throwPoint) {
if (!$throwPoint->isExplicit() && !$catchType->isSuperTypeOf(new ObjectType(Throwable::class))->yes()) {
continue;
}
$isSuperType = $catchType->isSuperTypeOf($throwPoint->getType());
if ($isSuperType->no()) {
continue;
$matchingThrowPoints = $isThrowable ? $throwPoints : [];

// explicit only
if (count($matchingThrowPoints) === 0) {
foreach ($throwPoints as $throwPoint) {
if (!$throwPoint->isExplicit() || $catchType->isSuperTypeOf($throwPoint->getType())->no()) {
continue;
}

$matchingThrowPoints[] = $throwPoint;
}
$matchingThrowPoints[] = $throwPoint;
}
$hasExplicit = count($matchingThrowPoints) > 0;
foreach ($throwPoints as $throwPoint) {
$isSuperType = $catchType->isSuperTypeOf($throwPoint->getType());
if (!$hasExplicit && !$isSuperType->no()) {

// implicit only
if (count($matchingThrowPoints) === 0) {
foreach ($throwPoints as $throwPoint) {
if ($throwPoint->isExplicit() || $catchType->isSuperTypeOf($throwPoint->getType())->no()) {
continue;
}

$matchingThrowPoints[] = $throwPoint;
}
if ($isSuperType->yes()) {
continue;
}
if ($isThrowable->yes()) {
continue;
}

// include previously removed throw points
if (count($matchingThrowPoints) === 0 && $isThrowable) {
foreach ($branchScopeResult->getThrowPoints() as $originalThrowPoint) {
if (!$originalThrowPoint->canContainAnyThrowable()) {
continue;
}

$matchingThrowPoints[] = $originalThrowPoint;
}
$newThrowPoints[] = $throwPoint->subtractCatchType($catchType);
}
$throwPoints = $newThrowPoints;

// emit error
if (count($matchingThrowPoints) === 0) {
$throwableThrowPoints = [];
if ($originalCatchType->isSuperTypeOf(new ObjectType(Throwable::class))->yes()) {
foreach ($branchScopeResult->getThrowPoints() as $originalThrowPoint) {
if (!$originalThrowPoint->canContainAnyThrowable()) {
continue;
}
$nodeCallback(new CatchWithUnthrownExceptionNode($catchNode, $catchType, $originalCatchType), $scope);
continue;
}

$throwableThrowPoints[] = $originalThrowPoint;
}
}
// recompute throw points
$newThrowPoints = [];
foreach ($throwPoints as $throwPoint) {
$newThrowPoint = $throwPoint->subtractCatchType($originalCatchType);

if (count($throwableThrowPoints) === 0) {
$nodeCallback(new CatchWithUnthrownExceptionNode($catchNode, $catchType, $originalCatchType), $scope);
if ($newThrowPoint->getType() instanceof NeverType) {
continue;
}

$matchingThrowPoints = $throwableThrowPoints;
$newThrowPoints[] = $newThrowPoint;
}
$throwPoints = $newThrowPoints;

$catchScope = null;
foreach ($matchingThrowPoints as $matchingThrowPoint) {
Expand Down

0 comments on commit b206ea8

Please sign in to comment.