mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
Trigger dispatch even when only legacy hooks (#4962)
This commit is contained in:
parent
7b43d321ad
commit
fe71e8d16b
@ -370,7 +370,7 @@ class ExistingAtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($config->eventDispatcher->after_method_checks) {
|
if ($config->eventDispatcher->hasAfterMethodCallAnalysisHandlers()) {
|
||||||
$file_manipulations = [];
|
$file_manipulations = [];
|
||||||
|
|
||||||
$appearing_method_id = $codebase->methods->getAppearingMethodId($method_id);
|
$appearing_method_id = $codebase->methods->getAppearingMethodId($method_id);
|
||||||
|
@ -469,7 +469,7 @@ class ExistingAtomicStaticCallAnalyzer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($config->eventDispatcher->after_method_checks) {
|
if ($config->eventDispatcher->hasAfterMethodCallAnalysisHandlers()) {
|
||||||
$file_manipulations = [];
|
$file_manipulations = [];
|
||||||
|
|
||||||
$appearing_method_id = $codebase->methods->getAppearingMethodId($method_id);
|
$appearing_method_id = $codebase->methods->getAppearingMethodId($method_id);
|
||||||
|
@ -6,6 +6,7 @@ use Psalm\Plugin\Hook;
|
|||||||
use Psalm\Plugin\EventHandler;
|
use Psalm\Plugin\EventHandler;
|
||||||
use Psalm\Plugin\EventHandler\Event;
|
use Psalm\Plugin\EventHandler\Event;
|
||||||
use Psalm\Type\Atomic\TLiteralString;
|
use Psalm\Type\Atomic\TLiteralString;
|
||||||
|
use function count;
|
||||||
use function is_subclass_of;
|
use function is_subclass_of;
|
||||||
|
|
||||||
|
|
||||||
@ -16,9 +17,9 @@ class EventDispatcher
|
|||||||
*
|
*
|
||||||
* @var list<class-string<EventHandler\AfterMethodCallAnalysisInterface>>
|
* @var list<class-string<EventHandler\AfterMethodCallAnalysisInterface>>
|
||||||
*/
|
*/
|
||||||
public $after_method_checks = [];
|
private $after_method_checks = [];
|
||||||
/** @var list<class-string<Hook\AfterMethodCallAnalysisInterface>> */
|
/** @var list<class-string<Hook\AfterMethodCallAnalysisInterface>> */
|
||||||
public $legacy_after_method_checks = [];
|
private $legacy_after_method_checks = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static methods to be called after project function checks have completed
|
* Static methods to be called after project function checks have completed
|
||||||
@ -96,9 +97,9 @@ class EventDispatcher
|
|||||||
*
|
*
|
||||||
* @var list<class-string<EventHandler\AfterClassLikeVisitInterface>>
|
* @var list<class-string<EventHandler\AfterClassLikeVisitInterface>>
|
||||||
*/
|
*/
|
||||||
public $after_visit_classlikes = [];
|
private $after_visit_classlikes = [];
|
||||||
/** @var list<class-string<Hook\AfterClassLikeVisitInterface>> */
|
/** @var list<class-string<Hook\AfterClassLikeVisitInterface>> */
|
||||||
public $legacy_after_visit_classlikes = [];
|
private $legacy_after_visit_classlikes = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static methods to be called after codebase has been populated
|
* Static methods to be called after codebase has been populated
|
||||||
@ -235,6 +236,11 @@ class EventDispatcher
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hasAfterMethodCallAnalysisHandlers(): bool
|
||||||
|
{
|
||||||
|
return count($this->after_method_checks) || count($this->legacy_after_method_checks);
|
||||||
|
}
|
||||||
|
|
||||||
public function dispatchAfterMethodCallAnalysis(Event\AfterMethodCallAnalysisEvent $event): void
|
public function dispatchAfterMethodCallAnalysis(Event\AfterMethodCallAnalysisEvent $event): void
|
||||||
{
|
{
|
||||||
foreach ($this->after_method_checks as $handler) {
|
foreach ($this->after_method_checks as $handler) {
|
||||||
@ -409,6 +415,11 @@ class EventDispatcher
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hasAfterClassLikeVisitHandlers(): bool
|
||||||
|
{
|
||||||
|
return count($this->after_visit_classlikes) || count($this->legacy_after_visit_classlikes);
|
||||||
|
}
|
||||||
|
|
||||||
public function dispatchAfterClassLikeVisit(Event\AfterClassLikeVisitEvent $event): void
|
public function dispatchAfterClassLikeVisit(Event\AfterClassLikeVisitEvent $event): void
|
||||||
{
|
{
|
||||||
foreach ($this->after_visit_classlikes as $handler) {
|
foreach ($this->after_visit_classlikes as $handler) {
|
||||||
|
@ -51,7 +51,7 @@ class ClassLikeStorageCacheProvider
|
|||||||
$storage_dir . 'MethodStorage.php',
|
$storage_dir . 'MethodStorage.php',
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($config->eventDispatcher->after_visit_classlikes) {
|
if ($config->eventDispatcher->hasAfterClassLikeVisitHandlers()) {
|
||||||
$dependent_files = array_merge($dependent_files, $config->plugin_paths);
|
$dependent_files = array_merge($dependent_files, $config->plugin_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ class FileStorageCacheProvider
|
|||||||
$storage_dir . 'FunctionLikeParameter.php',
|
$storage_dir . 'FunctionLikeParameter.php',
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($config->eventDispatcher->after_visit_classlikes) {
|
if ($config->eventDispatcher->hasAfterClassLikeVisitHandlers()) {
|
||||||
$dependent_files = array_merge($dependent_files, $config->plugin_paths);
|
$dependent_files = array_merge($dependent_files, $config->plugin_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Psalm\Tests\Config;
|
namespace Psalm\Tests\Config;
|
||||||
|
|
||||||
|
use PhpParser\Node\Expr;
|
||||||
|
use PhpParser\Node\Stmt\ClassLike;
|
||||||
use PHPUnit\Framework\MockObject\MockObject;
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
use Psalm\Codebase;
|
||||||
|
use Psalm\FileSource;
|
||||||
use Psalm\Plugin\EventHandler\AfterEveryFunctionCallAnalysisInterface;
|
use Psalm\Plugin\EventHandler\AfterEveryFunctionCallAnalysisInterface;
|
||||||
use Psalm\Plugin\EventHandler\Event\AfterCodebasePopulatedEvent;
|
use Psalm\Plugin\EventHandler\Event\AfterCodebasePopulatedEvent;
|
||||||
use Psalm\Plugin\EventHandler\Event\AfterEveryFunctionCallAnalysisEvent;
|
use Psalm\Plugin\EventHandler\Event\AfterEveryFunctionCallAnalysisEvent;
|
||||||
|
use Psalm\Plugin\Hook\AfterClassLikeVisitInterface;
|
||||||
|
use Psalm\Plugin\Hook\AfterMethodCallAnalysisInterface;
|
||||||
|
use Psalm\StatementsSource;
|
||||||
|
use Psalm\Storage\ClassLikeStorage;
|
||||||
|
use Psalm\Type\Union;
|
||||||
use function define;
|
use function define;
|
||||||
use function defined;
|
use function defined;
|
||||||
use const DIRECTORY_SEPARATOR;
|
use const DIRECTORY_SEPARATOR;
|
||||||
@ -549,6 +558,82 @@ class PluginTest extends \Psalm\Tests\TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testAfterMethodCallAnalysisLegacyHookIsLoaded(): void
|
||||||
|
{
|
||||||
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
||||||
|
TestConfig::loadFromXML(
|
||||||
|
dirname(__DIR__, 2) . DIRECTORY_SEPARATOR,
|
||||||
|
'<?xml version="1.0"?>
|
||||||
|
<psalm
|
||||||
|
errorLevel="1"
|
||||||
|
>
|
||||||
|
<projectFiles>
|
||||||
|
<directory name="src" />
|
||||||
|
</projectFiles>
|
||||||
|
</psalm>'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$hook = new class implements AfterMethodCallAnalysisInterface {
|
||||||
|
public static function afterMethodCallAnalysis(
|
||||||
|
Expr $expr,
|
||||||
|
string $method_id,
|
||||||
|
string $appearing_method_id,
|
||||||
|
string $declaring_method_id,
|
||||||
|
Context $context,
|
||||||
|
StatementsSource $statements_source,
|
||||||
|
Codebase $codebase,
|
||||||
|
array &$file_replacements = [],
|
||||||
|
Union &$return_type_candidate = null
|
||||||
|
): void {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$codebase = $this->project_analyzer->getCodebase();
|
||||||
|
|
||||||
|
$config = $codebase->config;
|
||||||
|
|
||||||
|
(new PluginRegistrationSocket($config, $codebase))->registerHooksFromClass(get_class($hook));
|
||||||
|
|
||||||
|
$this->assertTrue($this->project_analyzer->getCodebase()->config->eventDispatcher->hasAfterMethodCallAnalysisHandlers());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAfterClassLikeAnalysisLegacyHookIsLoaded(): void
|
||||||
|
{
|
||||||
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
||||||
|
TestConfig::loadFromXML(
|
||||||
|
dirname(__DIR__, 2) . DIRECTORY_SEPARATOR,
|
||||||
|
'<?xml version="1.0"?>
|
||||||
|
<psalm
|
||||||
|
errorLevel="1"
|
||||||
|
>
|
||||||
|
<projectFiles>
|
||||||
|
<directory name="src" />
|
||||||
|
</projectFiles>
|
||||||
|
</psalm>'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$hook = new class implements AfterClassLikeVisitInterface {
|
||||||
|
public static function afterClassLikeVisit(
|
||||||
|
ClassLike $stmt,
|
||||||
|
ClassLikeStorage $storage,
|
||||||
|
FileSource $statements_source,
|
||||||
|
Codebase $codebase,
|
||||||
|
array &$file_replacements = []
|
||||||
|
): void {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$codebase = $this->project_analyzer->getCodebase();
|
||||||
|
|
||||||
|
$config = $codebase->config;
|
||||||
|
|
||||||
|
(new PluginRegistrationSocket($config, $codebase))->registerHooksFromClass(get_class($hook));
|
||||||
|
|
||||||
|
$this->assertTrue($this->project_analyzer->getCodebase()->config->eventDispatcher->hasAfterClassLikeVisitHandlers());
|
||||||
|
}
|
||||||
|
|
||||||
public function testPropertyProviderHooks(): void
|
public function testPropertyProviderHooks(): void
|
||||||
{
|
{
|
||||||
require_once __DIR__ . '/Plugin/PropertyPlugin.php';
|
require_once __DIR__ . '/Plugin/PropertyPlugin.php';
|
||||||
|
Loading…
Reference in New Issue
Block a user