mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 05:41:20 +01:00
Infer types from numeric operations
This commit is contained in:
parent
9f9e8a1b30
commit
e89a2929d5
@ -366,7 +366,8 @@ class AssignmentChecker
|
||||
$stmt->var,
|
||||
$stmt->expr,
|
||||
$stmt,
|
||||
$result_type
|
||||
$result_type,
|
||||
$context
|
||||
);
|
||||
|
||||
if ($result_type && $var_id) {
|
||||
|
@ -1069,17 +1069,32 @@ class ExpressionChecker
|
||||
$stmt->left,
|
||||
$stmt->right,
|
||||
$stmt,
|
||||
$result_type
|
||||
$result_type,
|
||||
$context
|
||||
);
|
||||
|
||||
if ($result_type) {
|
||||
$stmt->inferredType = $result_type;
|
||||
}
|
||||
} elseif ($stmt instanceof PhpParser\Node\Expr\BinaryOp\Div
|
||||
&& ($stmt->left->inferredType->hasInt() || $stmt->left->inferredType->hasFloat())
|
||||
&& ($stmt->right->inferredType->hasInt() || $stmt->right->inferredType->hasFloat())
|
||||
} elseif ($stmt instanceof PhpParser\Node\Expr\BinaryOp\Div) {
|
||||
$project_checker = $statements_checker->getFileChecker()->project_checker;
|
||||
|
||||
if ($project_checker->infer_types_from_usage
|
||||
&& isset($stmt->left->inferredType)
|
||||
&& isset($stmt->right->inferredType)
|
||||
&& ($stmt->left->inferredType->isMixed() || $stmt->right->inferredType->isMixed())
|
||||
) {
|
||||
$stmt->inferredType = Type::combineUnionTypes(Type::getFloat(), Type::getInt());
|
||||
$source_checker = $statements_checker->getSource();
|
||||
|
||||
if ($source_checker instanceof FunctionLikeChecker) {
|
||||
$function_storage = $source_checker->getFunctionLikeStorage();
|
||||
|
||||
$context->inferType($stmt->left, $function_storage, new Type\Union([new TInt, new TFloat]));
|
||||
$context->inferType($stmt->right, $function_storage, new Type\Union([new TInt, new TFloat]));
|
||||
}
|
||||
}
|
||||
|
||||
$stmt->inferredType = new Type\Union([new TInt, new TFloat]);
|
||||
} elseif ($stmt instanceof PhpParser\Node\Expr\BinaryOp\Concat) {
|
||||
self::analyzeConcatOp(
|
||||
$statements_checker,
|
||||
@ -1132,12 +1147,31 @@ class ExpressionChecker
|
||||
PhpParser\Node\Expr $left,
|
||||
PhpParser\Node\Expr $right,
|
||||
PhpParser\Node $parent,
|
||||
Type\Union &$result_type = null
|
||||
Type\Union &$result_type = null,
|
||||
Context $context = null
|
||||
) {
|
||||
$project_checker = $statements_source->getFileChecker()->project_checker;
|
||||
|
||||
$left_type = isset($left->inferredType) ? $left->inferredType : null;
|
||||
$right_type = isset($right->inferredType) ? $right->inferredType : null;
|
||||
$config = Config::getInstance();
|
||||
|
||||
if ($project_checker->infer_types_from_usage
|
||||
&& $context
|
||||
&& $left_type
|
||||
&& $right_type
|
||||
&& ($left_type->isMixed() || $right_type->isMixed())
|
||||
&& ($left_type->hasNumericType() || $right_type->hasNumericType())
|
||||
) {
|
||||
$source_checker = $statements_source->getSource();
|
||||
if ($source_checker instanceof FunctionLikeChecker) {
|
||||
$function_storage = $source_checker->getFunctionLikeStorage();
|
||||
|
||||
$context->inferType($left, $function_storage, new Type\Union([new TInt, new TFloat]));
|
||||
$context->inferType($right, $function_storage, new Type\Union([new TInt, new TFloat]));
|
||||
}
|
||||
}
|
||||
|
||||
if ($left_type && $right_type) {
|
||||
foreach ($left_type->types as $left_type_part) {
|
||||
foreach ($right_type->types as $right_type_part) {
|
||||
|
@ -399,6 +399,24 @@ class AnnotationTest extends TestCase
|
||||
. ' should be string',
|
||||
'error_levels' => ['MixedOperand'],
|
||||
],
|
||||
'noParamTypeButAddition' => [
|
||||
'<?php
|
||||
function fooFoo($a) : void {
|
||||
echo $a + 5;
|
||||
}',
|
||||
'error_message' => 'UntypedParam - src/somefile.php:2 - Parameter $a has no provided type,'
|
||||
. ' should be int|float',
|
||||
'error_levels' => ['MixedOperand', 'MixedArgument'],
|
||||
],
|
||||
'noParamTypeButDivision' => [
|
||||
'<?php
|
||||
function fooFoo($a) : void {
|
||||
echo $a / 5;
|
||||
}',
|
||||
'error_message' => 'UntypedParam - src/somefile.php:2 - Parameter $a has no provided type,'
|
||||
. ' should be int|float',
|
||||
'error_levels' => ['MixedOperand', 'MixedArgument'],
|
||||
],
|
||||
'noParamTypeButTemplatedString' => [
|
||||
'<?php
|
||||
function fooFoo($a) : void {
|
||||
|
Loading…
x
Reference in New Issue
Block a user