1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

Detect never-return statement same as a throw

This commit is contained in:
Brown 2020-05-26 15:02:23 -04:00
parent a2b6326a84
commit f0a5bd74b6
3 changed files with 39 additions and 2 deletions

View File

@ -393,7 +393,7 @@ class ReturnTypeAnalyzer
return null; return null;
} }
if (ScopeAnalyzer::onlyThrowsOrExits($function_stmts)) { if (ScopeAnalyzer::onlyThrowsOrExits($type_provider, $function_stmts)) {
// if there's a single throw statement, it's presumably an exception saying this method is not to be // if there's a single throw statement, it's presumably an exception saying this method is not to be
// used // used
return null; return null;

View File

@ -346,7 +346,7 @@ class ScopeAnalyzer
* *
* @return bool * @return bool
*/ */
public static function onlyThrowsOrExits(array $stmts) public static function onlyThrowsOrExits(\Psalm\NodeTypeProvider $type_provider, array $stmts)
{ {
if (empty($stmts)) { if (empty($stmts)) {
return false; return false;
@ -361,6 +361,14 @@ class ScopeAnalyzer
) { ) {
return true; return true;
} }
if ($stmt instanceof PhpParser\Node\Stmt\Expression) {
$stmt_type = $type_provider->getType($stmt->expr);
if ($stmt_type && $stmt_type->isNever()) {
return true;
}
}
} }
return false; return false;

View File

@ -814,6 +814,35 @@ class ReturnTypeTest extends TestCase
echo "$k\n"; echo "$k\n";
}' }'
], ],
'allowImplicitNever' => [
'<?php
class TestCase
{
/** @psalm-return never-return */
public function markAsSkipped(): void
{
throw new \Exception();
}
}
class A extends TestCase
{
/**
* @return string[]
*/
public function foo(): array
{
$this->markAsSkipped();
}
}
class B extends A
{
public function foo(): array
{
return ["foo"];
}
}'
],
]; ];
} }