From ee4a3882a7272fd6f2987f362b43a80cc063d0c8 Mon Sep 17 00:00:00 2001 From: Matthew Brown Date: Fri, 30 Dec 2016 23:40:32 -0500 Subject: [PATCH] Check method defaults to see whether they match --- config.xsd | 1 + src/Psalm/Checker/FunctionChecker.php | 2 +- src/Psalm/Checker/FunctionLikeChecker.php | 21 ++++++++++++++++++++- src/Psalm/Issue/InvalidParamDefault.php | 6 ++++++ tests/MethodSignatureTest.php | 19 +++++++++++++++++++ 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 src/Psalm/Issue/InvalidParamDefault.php diff --git a/config.xsd b/config.xsd index c8b1344c7..c8e0e661c 100644 --- a/config.xsd +++ b/config.xsd @@ -84,6 +84,7 @@ + diff --git a/src/Psalm/Checker/FunctionChecker.php b/src/Psalm/Checker/FunctionChecker.php index ad24dae35..78d5913bd 100644 --- a/src/Psalm/Checker/FunctionChecker.php +++ b/src/Psalm/Checker/FunctionChecker.php @@ -76,7 +76,7 @@ class FunctionChecker extends FunctionLikeChecker /** * @param string $function_id * @param string $file_path - * @return array + * @return array */ public static function getParams($function_id, $file_path) { diff --git a/src/Psalm/Checker/FunctionLikeChecker.php b/src/Psalm/Checker/FunctionLikeChecker.php index 482bd819e..ff35bd28a 100644 --- a/src/Psalm/Checker/FunctionLikeChecker.php +++ b/src/Psalm/Checker/FunctionLikeChecker.php @@ -13,6 +13,7 @@ use Psalm\EffectsAnalyser; use Psalm\Exception\DocblockParseException; use Psalm\FunctionLikeParameter; use Psalm\Issue\InvalidDocblock; +use Psalm\Issue\InvalidParamDefault; use Psalm\Issue\InvalidReturnType; use Psalm\Issue\InvalidToString; use Psalm\Issue\MethodSignatureMismatch; @@ -340,7 +341,7 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo ]); } - foreach ($function_params as $function_param) { + foreach ($function_params as $offset => $function_param) { $param_type = ExpressionChecker::fleshOutTypes( clone $function_param->type, [], @@ -352,6 +353,24 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo throw new \UnexpectedValueException('We should know where this code is'); } + $parser_param = $this->function->getParams()[$offset]; + + if ($parser_param->default) { + $default_type = StatementsChecker::getSimpleType($parser_param->default); + + if ($default_type && !TypeChecker::isContainedBy($default_type, $param_type)) { + if (IssueBuffer::accepts( + new InvalidParamDefault( + 'Default value for argument ' . ($offset + 1) . ' of method ' . $this->getMethodId() . + ' does not match the given type ' . $param_type, + $function_param->code_location + ) + )) { + return false; + } + } + } + foreach ($param_type->types as $atomic_type) { if ($atomic_type->isObjectType() && !$atomic_type->isObject() diff --git a/src/Psalm/Issue/InvalidParamDefault.php b/src/Psalm/Issue/InvalidParamDefault.php new file mode 100644 index 000000000..bb70a8b27 --- /dev/null +++ b/src/Psalm/Issue/InvalidParamDefault.php @@ -0,0 +1,6 @@ +check(true, true, $context); } + + /** + * @expectedException \Psalm\Exception\CodeException + * @expectedExceptionMessage InvalidParamDefault + */ + public function testInvalidDefault() + { + $stmts = self::$parser->parse('check(true, true, $context); + } }