mirror of
https://github.com/danog/psalm-plugin-laravel.git
synced 2024-11-30 04:39:01 +01:00
refactor: generalize SuppressHandler
This commit is contained in:
parent
fc80186694
commit
aebbf15e48
@ -2,73 +2,108 @@
|
||||
|
||||
namespace Psalm\LaravelPlugin\Handlers;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Psalm\Plugin\EventHandler\AfterClassLikeVisitInterface;
|
||||
use Psalm\Plugin\EventHandler\Event\AfterClassLikeVisitEvent;
|
||||
use Psalm\Storage\ClassLikeStorage;
|
||||
use Psalm\Storage\MethodStorage;
|
||||
use function array_key_exists;
|
||||
use Psalm\Storage\PropertyStorage;
|
||||
use function array_intersect;
|
||||
use function in_array;
|
||||
|
||||
class SuppressHandler implements AfterClassLikeVisitInterface
|
||||
{
|
||||
private const UNUSED_CLASSES = [
|
||||
"App\Console\Kernel",
|
||||
"App\Exceptions\Handler",
|
||||
"App\Http\Controllers\Controller",
|
||||
"App\Http\Kernel",
|
||||
"App\Http\Middleware\Authenticate",
|
||||
"App\Http\Middleware\TrustHosts",
|
||||
"App\Providers\AppServiceProvider",
|
||||
"App\Providers\AuthServiceProvider",
|
||||
"App\Providers\BroadcastServiceProvider",
|
||||
"App\Providers\EventServiceProvider",
|
||||
/**
|
||||
* @var array<string, list<class-string>>
|
||||
*/
|
||||
private const BY_CLASS = [
|
||||
'UnusedClass' => [
|
||||
'App\Console\Kernel',
|
||||
'App\Exceptions\Handler',
|
||||
'App\Http\Controllers\Controller',
|
||||
'App\Http\Kernel',
|
||||
'App\Http\Middleware\Authenticate',
|
||||
'App\Http\Middleware\TrustHosts',
|
||||
'App\Providers\AppServiceProvider',
|
||||
'App\Providers\AuthServiceProvider',
|
||||
'App\Providers\BroadcastServiceProvider',
|
||||
'App\Providers\EventServiceProvider',
|
||||
],
|
||||
];
|
||||
|
||||
private const UNUSED_METHODS = [
|
||||
"App\Http\Middleware\RedirectIfAuthenticated" => ["handle"],
|
||||
/**
|
||||
* @var array<string, array<class-string, list<string>>>
|
||||
*/
|
||||
private const BY_CLASS_METHOD = [
|
||||
'PossiblyUnusedMethod' => [
|
||||
'App\Http\Middleware\RedirectIfAuthenticated' => ['handle'],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array<string, list<class-string>>
|
||||
*/
|
||||
private const BY_PARENT_CLASS = [
|
||||
'PropertyNotSetInConstructor' => [
|
||||
'Illuminate\Console\Command',
|
||||
'Illuminate\Foundation\Http\FormRequest',
|
||||
'Illuminate\Notifications\Notification',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array<string, array<class-string, list<string>>>
|
||||
*/
|
||||
private const BY_PARENT_CLASS_PROPERTY = [
|
||||
'NonInvariantDocblockPropertyType' => [
|
||||
'Illuminate\Console\Command' => ['description'],
|
||||
],
|
||||
];
|
||||
|
||||
public static function afterClassLikeVisit(AfterClassLikeVisitEvent $event)
|
||||
{
|
||||
$storage = $event->getStorage();
|
||||
$class = $event->getStorage();
|
||||
|
||||
if (in_array(Command::class, $storage->parent_classes)) {
|
||||
if (!in_array('PropertyNotSetInConstructor', $storage->suppressed_issues)) {
|
||||
$storage->suppressed_issues[] = 'PropertyNotSetInConstructor';
|
||||
foreach (self::BY_CLASS as $issue => $class_names) {
|
||||
if (in_array($class->name, $class_names)) {
|
||||
self::suppress($issue, $class);
|
||||
}
|
||||
if (isset($storage->properties['description'])) {
|
||||
$property = $storage->properties['description'];
|
||||
if (!in_array('NonInvariantDocblockPropertyType', $property->suppressed_issues)) {
|
||||
$property->suppressed_issues[] = 'NonInvariantDocblockPropertyType';
|
||||
}
|
||||
|
||||
foreach (self::BY_CLASS_METHOD as $issue => $method_by_class) {
|
||||
foreach ($method_by_class[$class->name] ?? [] as $method_name) {
|
||||
self::suppress($issue, $class->methods[$method_name] ?? null);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (self::BY_PARENT_CLASS as $issue => $parent_classes) {
|
||||
if (!array_intersect($class->parent_classes, $parent_classes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
self::suppress($issue, $class);
|
||||
}
|
||||
|
||||
foreach (self::BY_PARENT_CLASS_PROPERTY as $issue => $methods_by_parent_class) {
|
||||
foreach ($methods_by_parent_class as $parent_class => $property_names) {
|
||||
if (!in_array($parent_class, $class->parent_classes)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FormRequest: suppress PropertyNotSetInConstructor.
|
||||
if (in_array(FormRequest::class, $storage->parent_classes) && !in_array('PropertyNotSetInConstructor', $storage->suppressed_issues)) {
|
||||
$storage->suppressed_issues[] = 'PropertyNotSetInConstructor';
|
||||
}
|
||||
|
||||
// Notification: suppress PropertyNotSetInConstructor.
|
||||
if (in_array(Notification::class, $storage->parent_classes) && !in_array('PropertyNotSetInConstructor', $storage->suppressed_issues)) {
|
||||
$storage->suppressed_issues[] = 'PropertyNotSetInConstructor';
|
||||
}
|
||||
|
||||
// Suppress UnusedClass on well-known classes.
|
||||
if (in_array($storage->name, self::UNUSED_CLASSES)) {
|
||||
$storage->suppressed_issues[] = 'UnusedClass';
|
||||
}
|
||||
|
||||
// Suppress PossiblyUnusedMethod on well-known methods.
|
||||
if (array_key_exists($storage->name, self::UNUSED_METHODS)) {
|
||||
foreach (self::UNUSED_METHODS[$storage->name] as $method_name) {
|
||||
$method = $storage->methods[$method_name] ?? null;
|
||||
if ($method instanceof MethodStorage) {
|
||||
$method->suppressed_issues[] = 'PossiblyUnusedMethod';
|
||||
foreach ($property_names as $property_name) {
|
||||
self::suppress($issue, $class->properties[$property_name] ?? null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $issue
|
||||
* @param ClassLikeStorage|PropertyStorage|MethodStorage|null $storage
|
||||
*/
|
||||
private static function suppress(string $issue, $storage): void
|
||||
{
|
||||
if ($storage && !in_array($issue, $storage->suppressed_issues)) {
|
||||
$storage->suppressed_issues[] = $issue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user