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

Emit an InvalidReturnType when it should contain null, and introduct LessSpecificReturnType

This commit is contained in:
Matthew Brown 2017-03-18 12:18:17 -04:00
parent 9edae64ee2
commit e687887ba3
6 changed files with 22 additions and 14 deletions

View File

@ -113,6 +113,7 @@
<xs:element name="InvalidStaticInvocation" type="IssueHandlerType" minOccurs="0" /> <xs:element name="InvalidStaticInvocation" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InvalidStaticVariable" type="IssueHandlerType" minOccurs="0" /> <xs:element name="InvalidStaticVariable" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InvalidToString" type="IssueHandlerType" minOccurs="0" /> <xs:element name="InvalidToString" type="IssueHandlerType" minOccurs="0" />
<xs:element name="LessSpecificReturnType" type="IssueHandlerType" minOccurs="0" />
<xs:element name="MethodSignatureMismatch" type="IssueHandlerType" minOccurs="0" /> <xs:element name="MethodSignatureMismatch" type="IssueHandlerType" minOccurs="0" />
<xs:element name="MisplacedRequiredParam" type="IssueHandlerType" minOccurs="0" /> <xs:element name="MisplacedRequiredParam" type="IssueHandlerType" minOccurs="0" />
<xs:element name="MissingClosureReturnType" type="IssueHandlerType" minOccurs="0" /> <xs:element name="MissingClosureReturnType" type="IssueHandlerType" minOccurs="0" />

View File

@ -18,6 +18,7 @@ use Psalm\Issue\InvalidDocblock;
use Psalm\Issue\InvalidParamDefault; use Psalm\Issue\InvalidParamDefault;
use Psalm\Issue\InvalidReturnType; use Psalm\Issue\InvalidReturnType;
use Psalm\Issue\InvalidToString; use Psalm\Issue\InvalidToString;
use Psalm\Issue\LessSpecificReturnType;
use Psalm\Issue\MethodSignatureMismatch; use Psalm\Issue\MethodSignatureMismatch;
use Psalm\Issue\MisplacedRequiredParam; use Psalm\Issue\MisplacedRequiredParam;
use Psalm\Issue\MissingClosureReturnType; use Psalm\Issue\MissingClosureReturnType;
@ -1115,7 +1116,7 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
$inferred_return_type, $inferred_return_type,
$declared_return_type, $declared_return_type,
$this->getFileChecker(), $this->getFileChecker(),
true, false,
$has_scalar_match, $has_scalar_match,
$type_coerced $type_coerced
)) { )) {
@ -1131,7 +1132,7 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
if ($type_coerced) { if ($type_coerced) {
if (IssueBuffer::accepts( if (IssueBuffer::accepts(
new MoreSpecificReturnType( new MoreSpecificReturnType(
'The given return type \'' . $declared_return_type . '\' for ' . $cased_method_id . 'The declared return type \'' . $declared_return_type . '\' for ' . $cased_method_id .
' is more specific than the inferred return type \'' . $inferred_return_type . '\'', ' is more specific than the inferred return type \'' . $inferred_return_type . '\'',
$secondary_return_type_location ?: $return_type_location $secondary_return_type_location ?: $return_type_location
), ),
@ -1142,7 +1143,7 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
} else { } else {
if (IssueBuffer::accepts( if (IssueBuffer::accepts(
new InvalidReturnType( new InvalidReturnType(
'The given return type \'' . $declared_return_type . '\' for ' . $cased_method_id . 'The declared return type \'' . $declared_return_type . '\' for ' . $cased_method_id .
' is incorrect, got \'' . $inferred_return_type . '\'', ' is incorrect, got \'' . $inferred_return_type . '\'',
$secondary_return_type_location ?: $return_type_location $secondary_return_type_location ?: $return_type_location
), ),
@ -1151,7 +1152,7 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
return false; return false;
} }
} }
} elseif ($inferred_return_type->isNullable() !== $declared_return_type->isNullable()) { } elseif (!$inferred_return_type->isNullable() && $declared_return_type->isNullable()) {
if ($update_docblock) { if ($update_docblock) {
if (!in_array('InvalidReturnType', $this->suppressed_issues)) { if (!in_array('InvalidReturnType', $this->suppressed_issues)) {
$this->addDocblockReturnType($inferred_return_type); $this->addDocblockReturnType($inferred_return_type);
@ -1161,9 +1162,9 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
} }
if (IssueBuffer::accepts( if (IssueBuffer::accepts(
new MoreSpecificReturnType( new LessSpecificReturnType(
'The given return type \'' . $declared_return_type . '\' for ' . $cased_method_id . 'The inferred return type \'' . $inferred_return_type . '\' for ' . $cased_method_id .
' is more specific than the inferred return type \'' . $inferred_return_type . '\'', ' is more specific than the declared return type \'' . $declared_return_type . '\'',
$secondary_return_type_location ?: $return_type_location $secondary_return_type_location ?: $return_type_location
), ),
$this->suppressed_issues $this->suppressed_issues

View File

@ -0,0 +1,6 @@
<?php
namespace Psalm\Issue;
class LessSpecificReturnType extends CodeError
{
}

View File

@ -59,7 +59,7 @@ class JsonOutputTest extends PHPUnit_Framework_TestCase
$issue_data = IssueBuffer::getIssueData()[0]; $issue_data = IssueBuffer::getIssueData()[0];
$this->assertSame('somefile.php', $issue_data['file_path']); $this->assertSame('somefile.php', $issue_data['file_path']);
$this->assertSame('error', $issue_data['type']); $this->assertSame('error', $issue_data['type']);
$this->assertSame("The given return type 'string' for fooFoo is incorrect, got 'int'", $issue_data['message']); $this->assertSame("The declared return type 'string' for fooFoo is incorrect, got 'int'", $issue_data['message']);
$this->assertSame(2, $issue_data['line_number']); $this->assertSame(2, $issue_data['line_number']);
$this->assertSame( $this->assertSame(
'string', 'string',
@ -174,7 +174,7 @@ class JsonOutputTest extends PHPUnit_Framework_TestCase
$issue_data = IssueBuffer::getIssueData()[0]; $issue_data = IssueBuffer::getIssueData()[0];
$this->assertSame('somefile.php', $issue_data['file_path']); $this->assertSame('somefile.php', $issue_data['file_path']);
$this->assertSame('error', $issue_data['type']); $this->assertSame('error', $issue_data['type']);
$this->assertSame('The given return type \'int\' for fooFoo is incorrect, got \'string\'', $issue_data['message']); $this->assertSame('The declared return type \'int\' for fooFoo is incorrect, got \'string\'', $issue_data['message']);
$this->assertSame(3, $issue_data['line_number']); $this->assertSame(3, $issue_data['line_number']);
$this->assertSame( $this->assertSame(
'@return int', '@return int',
@ -203,7 +203,7 @@ class JsonOutputTest extends PHPUnit_Framework_TestCase
$issue_data = IssueBuffer::getIssueData()[0]; $issue_data = IssueBuffer::getIssueData()[0];
$this->assertSame('somefile.php', $issue_data['file_path']); $this->assertSame('somefile.php', $issue_data['file_path']);
$this->assertSame('error', $issue_data['type']); $this->assertSame('error', $issue_data['type']);
$this->assertSame('The given return type \'int\' for fooFoo is incorrect, got \'string\'', $issue_data['message']); $this->assertSame('The declared return type \'int\' for fooFoo is incorrect, got \'string\'', $issue_data['message']);
$this->assertSame(2, $issue_data['line_number']); $this->assertSame(2, $issue_data['line_number']);
$this->assertSame( $this->assertSame(
'@return int', '@return int',

View File

@ -583,7 +583,7 @@ class ReturnTypeTest extends PHPUnit_Framework_TestCase
/** /**
* @expectedException \Psalm\Exception\CodeException * @expectedException \Psalm\Exception\CodeException
* @expectedExceptionMessage MoreSpecificReturnType * @expectedExceptionMessage InvalidReturnType
* @return void * @return void
*/ */
public function testWrongReturnType2() public function testWrongReturnType2()
@ -621,7 +621,7 @@ class ReturnTypeTest extends PHPUnit_Framework_TestCase
/** /**
* @expectedException \Psalm\Exception\CodeException * @expectedException \Psalm\Exception\CodeException
* @expectedExceptionMessage MoreSpecificReturnType * @expectedExceptionMessage InvalidReturnType
* @return void * @return void
*/ */
public function testWrongReturnTypeInNamespace2() public function testWrongReturnTypeInNamespace2()

View File

@ -265,7 +265,7 @@ class TypeAlgebraTest extends PHPUnit_Framework_TestCase
/** /**
* @expectedException \Psalm\Exception\CodeException * @expectedException \Psalm\Exception\CodeException
* @expectedExceptionMessage MoreSpecificReturnType * @expectedExceptionMessage InvalidReturnType
* @return void * @return void
*/ */
public function testInvertedTwoVarLogicNotNestedWithVarChange() public function testInvertedTwoVarLogicNotNestedWithVarChange()
@ -289,7 +289,7 @@ class TypeAlgebraTest extends PHPUnit_Framework_TestCase
/** /**
* @expectedException \Psalm\Exception\CodeException * @expectedException \Psalm\Exception\CodeException
* @expectedExceptionMessage MoreSpecificReturnType * @expectedExceptionMessage InvalidReturnType
* @return void * @return void
*/ */
public function testInvertedTwoVarLogicNotNestedWithElseif() public function testInvertedTwoVarLogicNotNestedWithElseif()