1
0
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:
Brown 2019-01-31 18:40:40 -05:00
parent e384fb0328
commit 3f289731bb
6 changed files with 61 additions and 8 deletions

View File

@ -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>

View File

@ -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"/>

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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) {}