diff --git a/assets/config_levels/3.xml b/assets/config_levels/3.xml
index da06ca861..2d712812f 100644
--- a/assets/config_levels/3.xml
+++ b/assets/config_levels/3.xml
@@ -22,6 +22,7 @@
-
+
+
diff --git a/assets/config_levels/4.xml b/assets/config_levels/4.xml
index 401f26e61..672e5356f 100644
--- a/assets/config_levels/4.xml
+++ b/assets/config_levels/4.xml
@@ -23,7 +23,8 @@
-
+
+
diff --git a/assets/config_levels/5.xml b/assets/config_levels/5.xml
index a611fccd4..b57431b5b 100644
--- a/assets/config_levels/5.xml
+++ b/assets/config_levels/5.xml
@@ -23,7 +23,8 @@
-
+
+
diff --git a/config.xsd b/config.xsd
index 96c2e3180..c42fde1c3 100644
--- a/config.xsd
+++ b/config.xsd
@@ -141,9 +141,11 @@
+
+
diff --git a/src/Psalm/Checker/FunctionLikeChecker.php b/src/Psalm/Checker/FunctionLikeChecker.php
index 0c49d5dfa..4b88ef9de 100644
--- a/src/Psalm/Checker/FunctionLikeChecker.php
+++ b/src/Psalm/Checker/FunctionLikeChecker.php
@@ -22,7 +22,9 @@ use Psalm\Issue\LessSpecificReturnType;
use Psalm\Issue\MethodSignatureMismatch;
use Psalm\Issue\MismatchingDocblockParamType;
use Psalm\Issue\MismatchingDocblockReturnType;
+use Psalm\Issue\MissingClosureParamType;
use Psalm\Issue\MissingClosureReturnType;
+use Psalm\Issue\MissingParamType;
use Psalm\Issue\MissingReturnType;
use Psalm\Issue\MixedInferredReturnType;
use Psalm\Issue\MoreSpecificImplementedParamType;
@@ -30,7 +32,6 @@ use Psalm\Issue\MoreSpecificImplementedReturnType;
use Psalm\Issue\MoreSpecificReturnType;
use Psalm\Issue\OverriddenMethodAccess;
use Psalm\Issue\ReservedWord;
-use Psalm\Issue\UntypedParam;
use Psalm\Issue\UnusedParam;
use Psalm\IssueBuffer;
use Psalm\StatementsSource;
@@ -525,13 +526,23 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
? ', ' . ($possible_type ? 'should be ' . $possible_type : 'could not infer type')
: '';
- IssueBuffer::accepts(
- new UntypedParam(
- 'Parameter $' . $function_param->name . ' has no provided type' . $infer_text,
- $function_param->location
- ),
- $storage->suppressed_issues
- );
+ if ($this->function instanceof Closure) {
+ IssueBuffer::accepts(
+ new MissingClosureParamType(
+ 'Parameter $' . $function_param->name . ' has no provided type' . $infer_text,
+ $function_param->location
+ ),
+ $storage->suppressed_issues
+ );
+ } else {
+ IssueBuffer::accepts(
+ new MissingParamType(
+ 'Parameter $' . $function_param->name . ' has no provided type' . $infer_text,
+ $function_param->location
+ ),
+ $storage->suppressed_issues
+ );
+ }
}
}
diff --git a/src/Psalm/Issue/MissingClosureParamType.php b/src/Psalm/Issue/MissingClosureParamType.php
new file mode 100644
index 000000000..d22654d6f
--- /dev/null
+++ b/src/Psalm/Issue/MissingClosureParamType.php
@@ -0,0 +1,6 @@
+ 'UntypedParam - src/somefile.php:2 - Parameter $a has no provided type,'
+ 'error_message' => 'MissingParamType - src/somefile.php:2 - Parameter $a has no provided type,'
. ' should be string',
'error_levels' => ['MixedArgument'],
],
@@ -567,7 +567,7 @@ class AnnotationTest extends TestCase
function fooFoo($a): void {
echo $a . "foo";
}',
- 'error_message' => 'UntypedParam - src/somefile.php:2 - Parameter $a has no provided type,'
+ 'error_message' => 'MissingParamType - src/somefile.php:2 - Parameter $a has no provided type,'
. ' should be string',
'error_levels' => ['MixedOperand'],
],
@@ -576,7 +576,7 @@ class AnnotationTest extends TestCase
function fooFoo($a): void {
echo $a + 5;
}',
- 'error_message' => 'UntypedParam - src/somefile.php:2 - Parameter $a has no provided type,'
+ 'error_message' => 'MissingParamType - src/somefile.php:2 - Parameter $a has no provided type,'
. ' should be int|float',
'error_levels' => ['MixedOperand', 'MixedArgument'],
],
@@ -585,7 +585,7 @@ class AnnotationTest extends TestCase
function fooFoo($a): void {
echo $a / 5;
}',
- 'error_message' => 'UntypedParam - src/somefile.php:2 - Parameter $a has no provided type,'
+ 'error_message' => 'MissingParamType - src/somefile.php:2 - Parameter $a has no provided type,'
. ' should be int|float',
'error_levels' => ['MixedOperand', 'MixedArgument'],
],
@@ -594,7 +594,7 @@ class AnnotationTest extends TestCase
function fooFoo($a): void {
echo "$a";
}',
- 'error_message' => 'UntypedParam - src/somefile.php:2 - Parameter $a has no provided type,'
+ 'error_message' => 'MissingParamType - src/somefile.php:2 - Parameter $a has no provided type,'
. ' should be string',
'error_levels' => ['MixedOperand'],
],
@@ -607,7 +607,7 @@ class AnnotationTest extends TestCase
echo substr("hello", $a, 2);
}
}',
- 'error_message' => 'UntypedParam - src/somefile.php:2 - Parameter $a has no provided type,'
+ 'error_message' => 'MissingParamType - src/somefile.php:2 - Parameter $a has no provided type,'
. ' should be int|string',
'error_levels' => ['MixedArgument'],
],
@@ -620,7 +620,7 @@ class AnnotationTest extends TestCase
class B extends A {
public function foo($a): void {}
}',
- 'error_message' => 'UntypedParam',
+ 'error_message' => 'MissingParamType',
'error_levels' => ['MethodSignatureMismatch'],
],
'alreadyHasCheck' => [
@@ -630,7 +630,7 @@ class AnnotationTest extends TestCase
function shouldTakeString($s): void {
if (is_string($s)) takesString($s);
}',
- 'error_message' => 'UntypedParam - src/somefile.php:4 - Parameter $s has no provided type,'
+ 'error_message' => 'MissingParamType - src/somefile.php:4 - Parameter $s has no provided type,'
. ' could not infer',
'error_levels' => ['MixedArgument'],
],
@@ -645,7 +645,7 @@ class AnnotationTest extends TestCase
$s = returnsMixed();
takesString($s);
}',
- 'error_message' => 'UntypedParam - src/somefile.php:7 - Parameter $s has no provided type,'
+ 'error_message' => 'MissingParamType - src/somefile.php:7 - Parameter $s has no provided type,'
. ' could not infer',
'error_levels' => ['MixedArgument', 'InvalidReturnType', 'MixedAssignment'],
],
diff --git a/tests/FunctionCallTest.php b/tests/FunctionCallTest.php
index d7886fe71..d629ff719 100644
--- a/tests/FunctionCallTest.php
+++ b/tests/FunctionCallTest.php
@@ -195,7 +195,12 @@ class FunctionCallTest extends TestCase
}
);',
'assertions' => [],
- 'error_levels' => ['MixedArrayAccess', 'MixedArgument', 'UntypedParam', 'MissingClosureReturnType'],
+ 'error_levels' => [
+ 'MixedArrayAccess',
+ 'MixedArgument',
+ 'MissingClosureParamType',
+ 'MissingClosureReturnType',
+ ],
],
'byRefAfterCallable' => [
' 'array',
],
'error_levels' => [
- 'UntypedParam',
+ 'MissingClosureParamType',
],
],
'arrayFilterUseKey' => [
@@ -535,7 +540,7 @@ class FunctionCallTest extends TestCase
*/
function f($p, $p) {}',
'error_message' => 'DuplicateParam',
- 'error_levels' => ['UntypedParam'],
+ 'error_levels' => ['MissingParamType'],
],
'invalidParamDefault' => [
'