mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
remove exitFunctions
This commit is contained in:
parent
0f2ae281ae
commit
b658b2738f
@ -16,14 +16,6 @@
|
||||
<xs:element name="mockClasses" type="MockClassesType" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="stubs" type="StubsType" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="plugins" type="PluginsType" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="exitFunctions" type="ExitFunctionsType" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<!-- note: for PHPStorm to mark the attribute as deprecated the doc entry has to be *single line* and start with the word `deprecated` -->
|
||||
<xs:documentation xml:lang="en">
|
||||
Deprecated. Replaced by documenting never as a return type. It is going to be removed in Psalm 5.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="forbiddenFunctions" type="ExitFunctionsType" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="issueHandlers" type="IssueHandlersType" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="ignoreExceptions" type="ExceptionsType" minOccurs="0" maxOccurs="1" />
|
||||
|
@ -502,13 +502,6 @@ class Config
|
||||
/** @var ClassLoader|null */
|
||||
private $composer_class_loader;
|
||||
|
||||
/**
|
||||
* Custom functions that always exit
|
||||
*
|
||||
* @var array<lowercase-string, bool>
|
||||
*/
|
||||
public $exit_functions = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
@ -1114,13 +1107,6 @@ class Config
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config_xml->exitFunctions) && isset($config_xml->exitFunctions->function)) {
|
||||
/** @var SimpleXMLElement $exit_function */
|
||||
foreach ($config_xml->exitFunctions->function as $exit_function) {
|
||||
$config->exit_functions[strtolower((string) $exit_function['name'])] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config_xml->stubs) && isset($config_xml->stubs->file)) {
|
||||
/** @var SimpleXMLElement $stub_file */
|
||||
foreach ($config_xml->stubs->file as $stub_file) {
|
||||
|
@ -156,7 +156,6 @@ class ReturnTypeAnalyzer
|
||||
&& ScopeAnalyzer::getControlActions(
|
||||
$function_stmts,
|
||||
$type_provider,
|
||||
$codebase->config->exit_functions,
|
||||
[]
|
||||
) !== [ScopeAnalyzer::ACTION_END]
|
||||
&& !$inferred_yield_types
|
||||
@ -177,7 +176,6 @@ class ReturnTypeAnalyzer
|
||||
$control_actions = ScopeAnalyzer::getControlActions(
|
||||
$function_stmts,
|
||||
$type_provider,
|
||||
$codebase->config->exit_functions,
|
||||
[],
|
||||
false
|
||||
);
|
||||
|
@ -31,8 +31,6 @@ class ReturnTypeCollector
|
||||
* @return list<Union> a list of return types
|
||||
*
|
||||
* @psalm-suppress ComplexMethod to be refactored
|
||||
*
|
||||
* TODO: This would probably benefit from using the list of exit_functions
|
||||
*/
|
||||
public static function getReturnTypes(
|
||||
Codebase $codebase,
|
||||
|
@ -533,7 +533,6 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
|
||||
$final_actions = ScopeAnalyzer::getControlActions(
|
||||
$this->function->getStmts() ?: [],
|
||||
null,
|
||||
$codebase->config->exit_functions,
|
||||
[]
|
||||
);
|
||||
|
||||
|
@ -14,7 +14,6 @@ use function array_unique;
|
||||
use function array_values;
|
||||
use function count;
|
||||
use function in_array;
|
||||
use function strtolower;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -67,7 +66,6 @@ class ScopeAnalyzer
|
||||
|
||||
/**
|
||||
* @param array<PhpParser\Node> $stmts
|
||||
* @param array<lowercase-string, bool> $exit_functions
|
||||
* @param list<'loop'|'switch'> $break_types
|
||||
* @param bool $return_is_exit Exit and Throw statements are treated differently from return if this is false
|
||||
*
|
||||
@ -78,7 +76,6 @@ class ScopeAnalyzer
|
||||
public static function getControlActions(
|
||||
array $stmts,
|
||||
?NodeDataProvider $nodes,
|
||||
array $exit_functions,
|
||||
array $break_types,
|
||||
bool $return_is_exit = true
|
||||
): array {
|
||||
@ -109,32 +106,6 @@ class ScopeAnalyzer
|
||||
return array_values(array_unique(array_merge($control_actions, [self::ACTION_END])));
|
||||
}
|
||||
|
||||
if ($exit_functions) {
|
||||
if ($stmt->expr instanceof PhpParser\Node\Expr\FuncCall
|
||||
|| $stmt->expr instanceof PhpParser\Node\Expr\StaticCall
|
||||
) {
|
||||
if ($stmt->expr instanceof PhpParser\Node\Expr\FuncCall) {
|
||||
/** @var string|null */
|
||||
$resolved_name = $stmt->expr->name->getAttribute('resolvedName');
|
||||
|
||||
if ($resolved_name && isset($exit_functions[strtolower($resolved_name)])) {
|
||||
return array_values(array_unique(array_merge($control_actions, [self::ACTION_END])));
|
||||
}
|
||||
} elseif ($stmt->expr->class instanceof PhpParser\Node\Name
|
||||
&& $stmt->expr->name instanceof PhpParser\Node\Identifier
|
||||
) {
|
||||
/** @var string|null */
|
||||
$resolved_class_name = $stmt->expr->class->getAttribute('resolvedName');
|
||||
|
||||
if ($resolved_class_name
|
||||
&& isset($exit_functions[strtolower($resolved_class_name . '::' . $stmt->expr->name)])
|
||||
) {
|
||||
return array_values(array_unique(array_merge($control_actions, [self::ACTION_END])));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -174,7 +145,6 @@ class ScopeAnalyzer
|
||||
$if_statement_actions = self::getControlActions(
|
||||
$stmt->stmts,
|
||||
$nodes,
|
||||
$exit_functions,
|
||||
$break_types,
|
||||
$return_is_exit
|
||||
);
|
||||
@ -190,7 +160,6 @@ class ScopeAnalyzer
|
||||
? self::getControlActions(
|
||||
$stmt->else->stmts,
|
||||
$nodes,
|
||||
$exit_functions,
|
||||
$break_types,
|
||||
$return_is_exit
|
||||
) : [];
|
||||
@ -211,7 +180,6 @@ class ScopeAnalyzer
|
||||
$elseif_control_actions = self::getControlActions(
|
||||
$elseif->stmts,
|
||||
$nodes,
|
||||
$exit_functions,
|
||||
$break_types,
|
||||
$return_is_exit
|
||||
);
|
||||
@ -268,7 +236,6 @@ class ScopeAnalyzer
|
||||
$case_actions = self::getControlActions(
|
||||
$case->stmts,
|
||||
$nodes,
|
||||
$exit_functions,
|
||||
array_merge($break_types, ['switch']),
|
||||
$return_is_exit
|
||||
);
|
||||
@ -334,7 +301,6 @@ class ScopeAnalyzer
|
||||
$loop_actions = self::getControlActions(
|
||||
$stmt->stmts,
|
||||
$nodes,
|
||||
$exit_functions,
|
||||
array_merge($break_types, ['loop']),
|
||||
$return_is_exit
|
||||
);
|
||||
@ -393,7 +359,6 @@ class ScopeAnalyzer
|
||||
$try_statement_actions = self::getControlActions(
|
||||
$stmt->stmts,
|
||||
$nodes,
|
||||
$exit_functions,
|
||||
$break_types,
|
||||
$return_is_exit
|
||||
);
|
||||
@ -414,7 +379,6 @@ class ScopeAnalyzer
|
||||
$catch_actions = self::getControlActions(
|
||||
$catch->stmts,
|
||||
$nodes,
|
||||
$exit_functions,
|
||||
$break_types,
|
||||
$return_is_exit
|
||||
);
|
||||
@ -453,7 +417,6 @@ class ScopeAnalyzer
|
||||
$finally_statement_actions = self::getControlActions(
|
||||
$stmt->finally->stmts,
|
||||
$nodes,
|
||||
$exit_functions,
|
||||
$break_types,
|
||||
$return_is_exit
|
||||
);
|
||||
|
@ -154,7 +154,6 @@ class ElseAnalyzer
|
||||
? ScopeAnalyzer::getControlActions(
|
||||
$else->stmts,
|
||||
$statements_analyzer->node_data,
|
||||
$codebase->config->exit_functions,
|
||||
[]
|
||||
)
|
||||
: [ScopeAnalyzer::ACTION_NONE];
|
||||
|
@ -312,7 +312,6 @@ class ElseIfAnalyzer
|
||||
$final_actions = ScopeAnalyzer::getControlActions(
|
||||
$elseif->stmts,
|
||||
$statements_analyzer->node_data,
|
||||
$codebase->config->exit_functions,
|
||||
[]
|
||||
);
|
||||
// has a return/throw at end
|
||||
|
@ -75,7 +75,6 @@ class IfAnalyzer
|
||||
$final_actions = ScopeAnalyzer::getControlActions(
|
||||
$stmt->stmts,
|
||||
$statements_analyzer->node_data,
|
||||
$codebase->config->exit_functions,
|
||||
[]
|
||||
);
|
||||
|
||||
|
@ -85,7 +85,6 @@ class IfElseAnalyzer
|
||||
$final_actions = ScopeAnalyzer::getControlActions(
|
||||
$stmt->stmts,
|
||||
null,
|
||||
$codebase->config->exit_functions,
|
||||
[]
|
||||
);
|
||||
|
||||
|
@ -4,7 +4,6 @@ namespace Psalm\Internal\Analyzer\Statements\Block;
|
||||
|
||||
use PhpParser;
|
||||
use Psalm\CodeLocation;
|
||||
use Psalm\Config;
|
||||
use Psalm\Context;
|
||||
use Psalm\Exception\ComplicatedExpressionException;
|
||||
use Psalm\Internal\Algebra;
|
||||
@ -96,7 +95,6 @@ class LoopAnalyzer
|
||||
$final_actions = ScopeAnalyzer::getControlActions(
|
||||
$stmts,
|
||||
$statements_analyzer->node_data,
|
||||
Config::getInstance()->exit_functions,
|
||||
[]
|
||||
);
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace Psalm\Internal\Analyzer\Statements\Block;
|
||||
|
||||
use PhpParser;
|
||||
use Psalm\Config;
|
||||
use Psalm\Context;
|
||||
use Psalm\Internal\Algebra;
|
||||
use Psalm\Internal\Analyzer\ScopeAnalyzer;
|
||||
@ -73,8 +72,6 @@ class SwitchAnalyzer
|
||||
|
||||
$case_action_map = [];
|
||||
|
||||
$config = Config::getInstance();
|
||||
|
||||
// create a map of case statement -> ultimate exit type
|
||||
for ($i = count($stmt->cases) - 1; $i >= 0; --$i) {
|
||||
$case = $stmt->cases[$i];
|
||||
@ -82,7 +79,6 @@ class SwitchAnalyzer
|
||||
$case_actions = $case_action_map[$i] = ScopeAnalyzer::getControlActions(
|
||||
$case->stmts,
|
||||
$statements_analyzer->node_data,
|
||||
$config->exit_functions,
|
||||
['switch']
|
||||
);
|
||||
|
||||
|
@ -52,7 +52,6 @@ class TryAnalyzer
|
||||
$catch_actions[$i] = ScopeAnalyzer::getControlActions(
|
||||
$catch->stmts,
|
||||
$statements_analyzer->node_data,
|
||||
$codebase->config->exit_functions,
|
||||
[]
|
||||
);
|
||||
$all_catches_leave = $all_catches_leave && !in_array(ScopeAnalyzer::ACTION_NONE, $catch_actions[$i], true);
|
||||
@ -105,7 +104,6 @@ class TryAnalyzer
|
||||
$try_block_control_actions = ScopeAnalyzer::getControlActions(
|
||||
$stmt->stmts,
|
||||
$statements_analyzer->node_data,
|
||||
$codebase->config->exit_functions,
|
||||
[]
|
||||
);
|
||||
|
||||
@ -359,7 +357,6 @@ class TryAnalyzer
|
||||
$catch_actions[$i] = ScopeAnalyzer::getControlActions(
|
||||
$catch->stmts,
|
||||
$statements_analyzer->node_data,
|
||||
$codebase->config->exit_functions,
|
||||
[]
|
||||
);
|
||||
|
||||
|
@ -300,7 +300,6 @@ class FunctionLikeNodeScanner
|
||||
$final_actions = ScopeAnalyzer::getControlActions(
|
||||
$function_stmt->stmts,
|
||||
null,
|
||||
$this->config->exit_functions,
|
||||
[],
|
||||
false
|
||||
);
|
||||
|
@ -869,73 +869,6 @@ class ConfigTest extends TestCase
|
||||
$this->analyzeFile($file_path, new Context());
|
||||
}
|
||||
|
||||
public function testExitFunctions(): void
|
||||
{
|
||||
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
||||
TestConfig::loadFromXML(
|
||||
dirname(__DIR__, 2),
|
||||
'<?xml version="1.0"?>
|
||||
<psalm>
|
||||
<exitFunctions>
|
||||
<function name="leave" />
|
||||
<function name="Foo\namespacedLeave" />
|
||||
<function name="Foo\Bar::staticLeave" />
|
||||
</exitFunctions>
|
||||
</psalm>'
|
||||
)
|
||||
);
|
||||
|
||||
$file_path = getcwd() . '/src/somefile.php';
|
||||
|
||||
$this->addFile(
|
||||
$file_path,
|
||||
'<?php
|
||||
namespace {
|
||||
function leave() : void {
|
||||
exit();
|
||||
}
|
||||
|
||||
function mightLeave() : string {
|
||||
if (rand(0, 1)) {
|
||||
leave();
|
||||
} else {
|
||||
return "here";
|
||||
}
|
||||
}
|
||||
|
||||
function mightLeaveWithNamespacedFunction() : string {
|
||||
if (rand(0, 1)) {
|
||||
\Foo\namespacedLeave();
|
||||
} else {
|
||||
return "here";
|
||||
}
|
||||
}
|
||||
|
||||
function mightLeaveWithStaticMethod() : string {
|
||||
if (rand(0, 1)) {
|
||||
Foo\Bar::staticLeave();
|
||||
} else {
|
||||
return "here";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Foo {
|
||||
function namespacedLeave() : void {
|
||||
exit();
|
||||
}
|
||||
|
||||
class Bar {
|
||||
public static function staticLeave() : void {
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}'
|
||||
);
|
||||
|
||||
$this->analyzeFile($file_path, new Context());
|
||||
}
|
||||
|
||||
public function testValidThrowInvalidCatch(): void
|
||||
{
|
||||
$this->expectExceptionMessage('InvalidCatch');
|
||||
|
Loading…
Reference in New Issue
Block a user