1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Fix #93 - fix MethodSignatureMismatch checks on builtin class methods

This commit is contained in:
Matthew Brown 2017-02-09 17:49:13 -05:00
parent a5922678ed
commit 41f7dc4a52
2 changed files with 97 additions and 3 deletions

View File

@ -164,6 +164,10 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
continue;
}
list($implemented_fq_class_name) = explode('::', $implemented_method_id);
$class_storage = ClassLikeChecker::$storage[strtolower($implemented_fq_class_name)];
$implemented_storage = MethodChecker::getStorage($implemented_method_id);
if ($implemented_storage->visibility < $storage->visibility) {
@ -200,8 +204,8 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
break;
}
if ((string)$storage->params[$i]->signature_type !==
(string)$implemented_param->signature_type
if ($class_storage->user_defined &&
(string)$storage->params[$i]->signature_type !== (string)$implemented_param->signature_type
) {
$cased_method_id = MethodChecker::getCasedMethodId((string)$this->getMethodId());
$parent_method_id = MethodChecker::getCasedMethodId($implemented_method_id);
@ -221,6 +225,29 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
$have_emitted = true;
break;
}
if (!$class_storage->user_defined &&
!$implemented_param->type->isMixed() &&
(string)$storage->params[$i]->type !== (string)$implemented_param->type
) {
$cased_method_id = MethodChecker::getCasedMethodId((string)$this->getMethodId());
$parent_method_id = MethodChecker::getCasedMethodId($implemented_method_id);
if (IssueBuffer::accepts(
new MethodSignatureMismatch(
'Argument ' . ($i + 1) . ' of ' . $cased_method_id .' has wrong type \'' .
$storage->params[$i]->type . '\', expecting \'' .
$implemented_param->type . '\' as defined by ' .
$parent_method_id,
$storage->params[$i]->code_location ?: new CodeLocation($this, $this->function, true)
)
)) {
return false;
}
$have_emitted = true;
break;
}
}
if ($storage->cased_name !== '__construct' &&
@ -604,7 +631,6 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
return $storage;
}
$docblock_info = null;
try {

View File

@ -114,4 +114,72 @@ class MethodSignatureTest extends PHPUnit_Framework_TestCase
$context = new Context();
$file_checker->visitAndAnalyzeMethods($context);
}
/**
* @return void
*/
public function testExtendDocblockParamType()
{
$stmts = self::$parser->parse('<?php
class A extends SoapClient
{
/**
* @param string $function_name
* @param array<mixed> $arguments
* @param array<mixed> $options default null
* @param array<mixed> $input_headers default null
* @param array<mixed> $output_headers default null
* @return mixed
*/
public function __soapCall(
$function_name,
$arguments,
$options = [],
$input_headers = [],
&$output_headers = []
) {
}
}
');
$file_checker = new FileChecker('somefile.php', $this->project_checker, $stmts);
$context = new Context();
$file_checker->visitAndAnalyzeMethods($context);
}
/**
* @expectedException \Psalm\Exception\CodeException
* @expectedExceptionMessage MethodSignatureMismatch
* @return void
*/
public function testExtendDocblockParamTypeWithWrongParam()
{
$stmts = self::$parser->parse('<?php
class A extends SoapClient
{
/**
* @param string $function_name
* @param string $arguments
* @param array<mixed> $options default null
* @param array<mixed> $input_headers default null
* @param array<mixed> $output_headers default null
* @return mixed
*/
public function __soapCall(
$function_name,
string $arguments,
$options = [],
$input_headers = [],
&$output_headers = []
) {
}
}
');
$file_checker = new FileChecker('somefile.php', $this->project_checker, $stmts);
$context = new Context();
$file_checker->visitAndAnalyzeMethods($context);
}
}