1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00

Add hook for plugins after FunctionLikeAnalysis (#3258)

This commit is contained in:
orklah 2020-04-28 21:30:51 +02:00 committed by GitHub
parent a0667f1543
commit 8571746f8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 0 deletions

View File

@ -19,6 +19,7 @@ class SomePlugin implements \Psalm\Plugin\Hook\AfterStatementAnalysisInterface
- `AfterEveryFunctionCallAnalysisInterface` - called after Psalm evaluates any function call. Cannot influence the call further.
- `AfterExpressionAnalysisInterface` - called after Psalm evaluates an expression.
- `AfterFunctionCallAnalysisInterface` - called after Psalm evaluates a function call to any function defined within the project itself. Can alter the return type or perform modifications of the call.
- `AfterFunctionLikeAnalysisInterface` - called after Psalm has completed its analysis of a given function-like.
- `AfterMethodCallAnalysisInterface` - called after Psalm analyzes a method call.
- `AfterStatementAnalysisInterface` - called after Psalm evaluates an statement.
- `FunctionExistenceProviderInterface` - can be used to override Psalm's builtin function existence checks for one or more functions.

View File

@ -496,6 +496,13 @@ class Config
*/
public $before_analyze_file = [];
/**
* Static methods to be called after functionlike checks have completed
*
* @var class-string<Hook\AfterFunctionLikeAnalysisInterface>[]
*/
public $after_functionlike_checks = [];
/** @var array<string, mixed> */
private $predefined_constants;

View File

@ -766,6 +766,31 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
}
}
$plugin_classes = $codebase->config->after_functionlike_checks;
if ($plugin_classes) {
$file_manipulations = [];
foreach ($plugin_classes as $plugin_fq_class_name) {
if ($plugin_fq_class_name::afterStatementAnalysis(
$this->function,
$storage,
$this,
$codebase,
$file_manipulations
) === false) {
return false;
}
}
if ($file_manipulations) {
\Psalm\Internal\FileManipulation\FileManipulationBuffer::add(
$this->getFilePath(),
$file_manipulations
);
}
}
return null;
}

View File

@ -0,0 +1,26 @@
<?php
namespace Psalm\Plugin\Hook;
use PhpParser\Node;
use Psalm\Codebase;
use Psalm\FileManipulation;
use Psalm\StatementsSource;
use Psalm\Storage\FunctionLikeStorage;
interface AfterFunctionLikeAnalysisInterface
{
/**
* Called after a statement has been checked
*
* @param FileManipulation[] $file_replacements
*
* @return null|false
*/
public static function afterStatementAnalysis(
Node\FunctionLike $stmt,
FunctionLikeStorage $classlike_storage,
StatementsSource $statements_source,
Codebase $codebase,
array &$file_replacements = []
);
}

View File

@ -121,5 +121,9 @@ class PluginRegistrationSocket implements RegistrationInterface
if (is_subclass_of($handler, Hook\StringInterpreterInterface::class)) {
$this->config->string_interpreters[$handler] = $handler;
}
if (is_subclass_of($handler, Hook\AfterFunctionLikeAnalysisInterface::class)) {
$this->config->after_functionlike_checks[$handler] = $handler;
}
}
}