mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 12:24:49 +01:00
Add ability to check descendants in ignored exceptions
This commit is contained in:
parent
e384fb0328
commit
3f289731bb
@ -95,7 +95,8 @@
|
||||
|
||||
<xs:complexType name="ExceptionsType">
|
||||
<xs:sequence>
|
||||
<xs:element name="class" maxOccurs="unbounded" type="NameAttributeType" />
|
||||
<xs:element name="class" minOccurs="0" maxOccurs="unbounded" type="NameAttributeType" />
|
||||
<xs:element name="classAndDescendants" minOccurs="0" maxOccurs="unbounded" type="NameAttributeType" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
<directory name="tests/stubs"/>
|
||||
<directory name="tests/DummyProject"/>
|
||||
<file name="vendor/phpunit/phpunit/src/Framework/TestCase.php"/>
|
||||
<file name="vendor/symfony/console/Command/Command.php" />
|
||||
<file name="src/Psalm/Internal/Traverser/CustomTraverser.php"/>
|
||||
<file name="tests/performance/a.test"/>
|
||||
<file name="tests/performance/b.test"/>
|
||||
|
@ -231,6 +231,11 @@ class Config
|
||||
*/
|
||||
public $ignored_exceptions = [];
|
||||
|
||||
/**
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
public $ignored_exceptions_and_descendants = [];
|
||||
|
||||
/**
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
@ -636,10 +641,18 @@ class Config
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config_xml->ignoreExceptions) && isset($config_xml->ignoreExceptions->class)) {
|
||||
/** @var \SimpleXMLElement $exception_class */
|
||||
foreach ($config_xml->ignoreExceptions->class as $exception_class) {
|
||||
$config->ignored_exceptions[(string) $exception_class['name']] = true;
|
||||
if (isset($config_xml->ignoreExceptions)) {
|
||||
if (isset($config_xml->ignoreExceptions->class)) {
|
||||
/** @var \SimpleXMLElement $exception_class */
|
||||
foreach ($config_xml->ignoreExceptions->class as $exception_class) {
|
||||
$config->ignored_exceptions[(string) $exception_class['name']] = true;
|
||||
}
|
||||
}
|
||||
if (isset($config_xml->ignoreExceptions->classAndDescendants)) {
|
||||
/** @var \SimpleXMLElement $exception_class */
|
||||
foreach ($config_xml->ignoreExceptions->classAndDescendants as $exception_class) {
|
||||
$config->ignored_exceptions_and_descendants[(string) $exception_class['name']] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -720,7 +720,12 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
|
||||
|
||||
if ($context->collect_exceptions) {
|
||||
if ($context->possibly_thrown_exceptions) {
|
||||
$ignored_exceptions = array_change_key_case($codebase->config->ignored_exceptions);
|
||||
$ignored_exceptions = array_change_key_case(
|
||||
$codebase->config->ignored_exceptions
|
||||
);
|
||||
$ignored_exceptions_and_descendants = array_change_key_case(
|
||||
$codebase->config->ignored_exceptions_and_descendants
|
||||
);
|
||||
|
||||
$undocumented_throws = [];
|
||||
|
||||
@ -736,6 +741,15 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($ignored_exceptions_and_descendants as $expected_exception => $_) {
|
||||
if ($expected_exception === $possibly_thrown_exception
|
||||
|| $codebase->classExtends($possibly_thrown_exception, $expected_exception)
|
||||
) {
|
||||
$is_expected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$is_expected) {
|
||||
$undocumented_throws[$possibly_thrown_exception] = true;
|
||||
}
|
||||
|
@ -688,6 +688,13 @@ class Populator
|
||||
if (isset($interface_storage->methods[$method_name])) {
|
||||
$interface_method_storage = $interface_storage->methods[$method_name];
|
||||
|
||||
if (!$method_storage->throws
|
||||
&& $method_storage->inheritdoc
|
||||
&& $interface_method_storage->throws
|
||||
) {
|
||||
$method_storage->throws = $interface_method_storage->throws;
|
||||
}
|
||||
|
||||
if ($interface_method_storage->return_type
|
||||
&& $interface_method_storage->signature_return_type
|
||||
&& $interface_method_storage->return_type
|
||||
@ -934,9 +941,18 @@ class Populator
|
||||
list($declaring_class, $declaring_method_name) = explode('::', $declaring_method_id);
|
||||
$declaring_class_storage = $this->classlike_storage_provider->get($declaring_class);
|
||||
|
||||
$declaring_method_storage = $declaring_class_storage->methods[strtolower($declaring_method_name)];
|
||||
|
||||
// tell the declaring class it's overridden downstream
|
||||
$declaring_class_storage->methods[strtolower($declaring_method_name)]->overridden_downstream = true;
|
||||
$declaring_class_storage->methods[strtolower($declaring_method_name)]->overridden_somewhere = true;
|
||||
$declaring_method_storage->overridden_downstream = true;
|
||||
$declaring_method_storage->overridden_somewhere = true;
|
||||
|
||||
if (!$method_storage->throws
|
||||
&& $method_storage->inheritdoc
|
||||
&& $declaring_method_storage->throws
|
||||
) {
|
||||
$method_storage->throws = $declaring_method_storage->throws;
|
||||
}
|
||||
|
||||
if (count($storage->overridden_method_ids[$method_name]) === 1
|
||||
&& $method_storage->signature_return_type
|
||||
|
@ -138,3 +138,11 @@ function array_search($needle, array $haystack, bool $strict = false) {}
|
||||
*/
|
||||
function usort(array &$arr, callable $callback): bool {}
|
||||
|
||||
/**
|
||||
* @psalm-template T
|
||||
*
|
||||
* @param array<string, T> $arr
|
||||
* @return array<string, T>
|
||||
*/
|
||||
function array_change_key_case(array $arr) {}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user