Skip to content

Commit

Permalink
TypeSpecifier - get rid of $defaultHandleFunctions
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Mar 26, 2021
1 parent 5becf4d commit 9720ad1
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 34 deletions.
18 changes: 8 additions & 10 deletions src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -1844,14 +1844,14 @@ private function resolveType(Expr $node): Type
$booleanConditionType = $conditionType->toBoolean();
if ($booleanConditionType instanceof ConstantBooleanType) {
if ($booleanConditionType->getValue()) {
return $this->filterByTruthyValue($node->cond, true)->getType($node->cond);
return $this->filterByTruthyValue($node->cond)->getType($node->cond);
}

return $this->filterByFalseyValue($node->cond, true)->getType($node->else);
return $this->filterByFalseyValue($node->cond)->getType($node->else);
}
return TypeCombinator::union(
TypeCombinator::remove($this->filterByTruthyValue($node->cond, true)->getType($node->cond), StaticTypeFactory::falsey()),
$this->filterByFalseyValue($node->cond, true)->getType($node->else)
TypeCombinator::remove($this->filterByTruthyValue($node->cond)->getType($node->cond), StaticTypeFactory::falsey()),
$this->filterByFalseyValue($node->cond)->getType($node->else)
);
}

Expand Down Expand Up @@ -3471,23 +3471,21 @@ public function removeTypeFromExpression(Expr $expr, Type $typeToRemove): self

/**
* @param \PhpParser\Node\Expr $expr
* @param bool $defaultHandleFunctions
* @return \PHPStan\Analyser\MutatingScope
*/
public function filterByTruthyValue(Expr $expr, bool $defaultHandleFunctions = false): Scope
public function filterByTruthyValue(Expr $expr): Scope
{
$specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($this, $expr, TypeSpecifierContext::createTruthy(), $defaultHandleFunctions);
$specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($this, $expr, TypeSpecifierContext::createTruthy());
return $this->filterBySpecifiedTypes($specifiedTypes);
}

/**
* @param \PhpParser\Node\Expr $expr
* @param bool $defaultHandleFunctions
* @return \PHPStan\Analyser\MutatingScope
*/
public function filterByFalseyValue(Expr $expr, bool $defaultHandleFunctions = false): Scope
public function filterByFalseyValue(Expr $expr): Scope
{
$specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($this, $expr, TypeSpecifierContext::createFalsey(), $defaultHandleFunctions);
$specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($this, $expr, TypeSpecifierContext::createFalsey());
return $this->filterBySpecifiedTypes($specifiedTypes);
}

Expand Down
4 changes: 2 additions & 2 deletions src/Analyser/Scope.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ public function getFunctionType($type, bool $isNullable, bool $isVariadic): Type

public function isInExpressionAssign(Expr $expr): bool;

public function filterByTruthyValue(Expr $expr, bool $defaultHandleFunctions = false): self;
public function filterByTruthyValue(Expr $expr): self;

public function filterByFalseyValue(Expr $expr, bool $defaultHandleFunctions = false): self;
public function filterByFalseyValue(Expr $expr): self;

public function isInFirstLevelStatement(): bool;

Expand Down
48 changes: 26 additions & 22 deletions src/Analyser/TypeSpecifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,7 @@ public function __construct(
public function specifyTypesInCondition(
Scope $scope,
Expr $expr,
TypeSpecifierContext $context,
bool $defaultHandleFunctions = false
TypeSpecifierContext $context
): SpecifiedTypes
{
if ($expr instanceof Instanceof_) {
Expand Down Expand Up @@ -517,10 +516,10 @@ public function specifyTypesInCondition(
return $result;

} elseif ($expr instanceof Node\Expr\BinaryOp\Greater) {
return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Smaller($expr->right, $expr->left), $context, $defaultHandleFunctions);
return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Smaller($expr->right, $expr->left), $context);

} elseif ($expr instanceof Node\Expr\BinaryOp\GreaterOrEqual) {
return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\SmallerOrEqual($expr->right, $expr->left), $context, $defaultHandleFunctions);
return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\SmallerOrEqual($expr->right, $expr->left), $context);

} elseif ($expr instanceof FuncCall && $expr->name instanceof Name) {
if ($this->reflectionProvider->hasFunction($expr->name, $scope)) {
Expand All @@ -534,9 +533,7 @@ public function specifyTypesInCondition(
}
}

if ($defaultHandleFunctions) {
return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope);
}
return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope);
} elseif ($expr instanceof MethodCall && $expr->name instanceof Node\Identifier) {
$methodCalledOnType = $scope->getType($expr->var);
$referencedClasses = TypeUtils::getDirectClassNames($methodCalledOnType);
Expand All @@ -557,9 +554,7 @@ public function specifyTypesInCondition(
}
}

if ($defaultHandleFunctions) {
return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope);
}
return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope);
} elseif ($expr instanceof StaticCall && $expr->name instanceof Node\Identifier) {
if ($expr->class instanceof Name) {
$calleeType = $scope->resolveTypeByName($expr->class);
Expand All @@ -585,9 +580,7 @@ public function specifyTypesInCondition(
}
}

if ($defaultHandleFunctions) {
return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope);
}
return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope);
} elseif ($expr instanceof BooleanAnd || $expr instanceof LogicalAnd) {
$leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context);
$rightTypes = $this->specifyTypesInCondition($scope, $expr->right, $context);
Expand Down Expand Up @@ -765,7 +758,7 @@ public function specifyTypesInCondition(
) {
return $this->create($expr->expr, new NonEmptyArrayType(), $context->negate(), false, $scope);
} elseif ($expr instanceof Expr\ErrorSuppress) {
return $this->specifyTypesInCondition($scope, $expr->expr, $context, $defaultHandleFunctions);
return $this->specifyTypesInCondition($scope, $expr->expr, $context);
} elseif (
$expr instanceof Expr\Ternary
&& !$context->null()
Expand All @@ -785,8 +778,7 @@ public function specifyTypesInCondition(
new Expr\BinaryOp\NotIdentical($expr->var, new ConstFetch(new Name('null'))),
new PropertyFetch($expr->var, $expr->name)
),
$context,
$defaultHandleFunctions
$context
);

$nullSafeTypes = $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope);
Expand All @@ -800,6 +792,9 @@ public function specifyTypesInCondition(

private function handleDefaultTruthyOrFalseyContext(TypeSpecifierContext $context, Expr $expr, Scope $scope): SpecifiedTypes
{
if ($context->null()) {
return new SpecifiedTypes();
}
if (!$context->truthy()) {
$type = StaticTypeFactory::truthy();
return $this->create($expr, $type, TypeSpecifierContext::createFalse(), false, $scope);
Expand Down Expand Up @@ -898,8 +893,13 @@ public function create(
if (
$expr instanceof FuncCall
&& $expr->name instanceof Name
&& $this->reflectionProvider->hasFunction($expr->name, $scope)
) {
$has = $this->reflectionProvider->hasFunction($expr->name, $scope);
if (!$has) {
// backwards compatibility with previous behaviour
return new SpecifiedTypes();
}

$functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope);
if ($functionReflection->hasSideEffects()->yes()) {
return new SpecifiedTypes();
Expand All @@ -913,11 +913,15 @@ public function create(
) {
$methodName = $expr->name->toString();
$calledOnType = $scope->getType($expr->var);
if ($calledOnType->hasMethod($methodName)->yes()) {
$methodReflection = $calledOnType->getMethod($methodName, $scope);
if ($methodReflection->hasSideEffects()->yes()) {
return new SpecifiedTypes();
}
$has = $calledOnType->hasMethod($methodName)->yes();
if (!$has) {
// backwards compatibility with previous behaviour
return new SpecifiedTypes();
}

$methodReflection = $calledOnType->getMethod($methodName, $scope);
if ($methodReflection->hasSideEffects()->yes()) {
return new SpecifiedTypes();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ function (): void {
assertType('int', rand(0, 1));
}
};
function (): void {
assertType('\'foo\'|int<min, -1>|int<1, max>', rand(0, 1) ?: 'foo');
assertType('\'foo\'|int', rand(0, 1) ? rand(0, 1) : 'foo');
};
}

public function doBar(): bool
Expand Down

0 comments on commit 9720ad1

Please sign in to comment.