mirror of
https://github.com/danog/psalm.git
synced 2024-11-27 04:45:20 +01:00
Use classes, not full method ids, for plugin execution
This commit is contained in:
parent
f159cd5146
commit
affcaebc3d
@ -297,13 +297,13 @@ abstract class ClassLikeChecker extends SourceChecker implements StatementsSourc
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!$inferred) {
|
if (!$inferred) {
|
||||||
$plugin_method_ids = $codebase->config->after_classlike_exists_checks;
|
$plugin_classes = $codebase->config->after_classlike_exists_checks;
|
||||||
|
|
||||||
if ($plugin_method_ids) {
|
if ($plugin_classes) {
|
||||||
$file_manipulations = [];
|
$file_manipulations = [];
|
||||||
|
|
||||||
foreach ($plugin_method_ids as $plugin_method_id) {
|
foreach ($plugin_classes as $plugin_fq_class_name) {
|
||||||
$plugin_method_id(
|
$plugin_fq_class_name::afterClassLikeExistsCheck(
|
||||||
$statements_source,
|
$statements_source,
|
||||||
$fq_class_name,
|
$fq_class_name,
|
||||||
$code_location,
|
$code_location,
|
||||||
@ -544,7 +544,7 @@ abstract class ClassLikeChecker extends SourceChecker implements StatementsSourc
|
|||||||
/**
|
/**
|
||||||
* @param string $file_path
|
* @param string $file_path
|
||||||
*
|
*
|
||||||
* @return array<string>
|
* @return array<string, string>
|
||||||
*/
|
*/
|
||||||
public static function getClassesForFile(ProjectChecker $project_checker, $file_path)
|
public static function getClassesForFile(ProjectChecker $project_checker, $file_path)
|
||||||
{
|
{
|
||||||
|
@ -445,8 +445,8 @@ class MethodCallChecker extends \Psalm\Checker\Statements\Expression\CallChecker
|
|||||||
$appearing_method_id = $codebase->methods->getAppearingMethodId($method_id);
|
$appearing_method_id = $codebase->methods->getAppearingMethodId($method_id);
|
||||||
$declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id);
|
$declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id);
|
||||||
|
|
||||||
foreach ($config->after_method_checks as $plugin_method_id) {
|
foreach ($config->after_method_checks as $plugin_fq_class_name) {
|
||||||
$plugin_method_id(
|
$plugin_fq_class_name::afterMethodCallCheck(
|
||||||
$statements_checker,
|
$statements_checker,
|
||||||
$method_id,
|
$method_id,
|
||||||
$appearing_method_id,
|
$appearing_method_id,
|
||||||
|
@ -9,6 +9,7 @@ use Psalm\Checker\StatementsChecker;
|
|||||||
use Psalm\CodeLocation;
|
use Psalm\CodeLocation;
|
||||||
use Psalm\Config;
|
use Psalm\Config;
|
||||||
use Psalm\Context;
|
use Psalm\Context;
|
||||||
|
use Psalm\FileManipulation\FileManipulationBuffer;
|
||||||
use Psalm\Issue\DeprecatedClass;
|
use Psalm\Issue\DeprecatedClass;
|
||||||
use Psalm\Issue\ParentNotFound;
|
use Psalm\Issue\ParentNotFound;
|
||||||
use Psalm\IssueBuffer;
|
use Psalm\IssueBuffer;
|
||||||
@ -182,6 +183,16 @@ class StaticCallChecker extends \Psalm\Checker\Statements\Expression\CallChecker
|
|||||||
$lhs_type = $stmt->class->inferredType;
|
$lhs_type = $stmt->class->inferredType;
|
||||||
|
|
||||||
if (!isset($lhs_type) || $lhs_type->hasString()) {
|
if (!isset($lhs_type) || $lhs_type->hasString()) {
|
||||||
|
if (self::checkFunctionArguments(
|
||||||
|
$statements_checker,
|
||||||
|
$stmt->args,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
$context
|
||||||
|
) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -336,6 +347,33 @@ class StaticCallChecker extends \Psalm\Checker\Statements\Expression\CallChecker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($config->after_method_checks) {
|
||||||
|
$file_manipulations = [];
|
||||||
|
|
||||||
|
$appearing_method_id = $codebase->methods->getAppearingMethodId($method_id);
|
||||||
|
$declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id);
|
||||||
|
|
||||||
|
$code_location = new CodeLocation($source, $stmt);
|
||||||
|
|
||||||
|
foreach ($config->after_method_checks as $plugin_fq_class_name) {
|
||||||
|
$plugin_fq_class_name::afterMethodCallCheck(
|
||||||
|
$statements_checker,
|
||||||
|
$method_id,
|
||||||
|
$appearing_method_id,
|
||||||
|
$declaring_method_id,
|
||||||
|
$stmt->args,
|
||||||
|
$code_location,
|
||||||
|
$file_manipulations,
|
||||||
|
$return_type_candidate
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($file_manipulations) {
|
||||||
|
/** @psalm-suppress MixedTypeCoercion */
|
||||||
|
FileManipulationBuffer::add($statements_checker->getFilePath(), $file_manipulations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($return_type_candidate) {
|
if ($return_type_candidate) {
|
||||||
if (isset($stmt->inferredType)) {
|
if (isset($stmt->inferredType)) {
|
||||||
$stmt->inferredType = Type::combineUnionTypes($stmt->inferredType, $return_type_candidate);
|
$stmt->inferredType = Type::combineUnionTypes($stmt->inferredType, $return_type_candidate);
|
||||||
|
@ -469,14 +469,14 @@ class ExpressionChecker
|
|||||||
|
|
||||||
$project_checker = $statements_checker->getFileChecker()->project_checker;
|
$project_checker = $statements_checker->getFileChecker()->project_checker;
|
||||||
|
|
||||||
$plugin_method_ids = $project_checker->config->after_expression_checks;
|
$plugin_classes = $project_checker->config->after_expression_checks;
|
||||||
|
|
||||||
if ($plugin_method_ids) {
|
if ($plugin_classes) {
|
||||||
$file_manipulations = [];
|
$file_manipulations = [];
|
||||||
$code_location = new CodeLocation($statements_checker->getSource(), $stmt);
|
$code_location = new CodeLocation($statements_checker->getSource(), $stmt);
|
||||||
|
|
||||||
foreach ($plugin_method_ids as $plugin_method_id) {
|
foreach ($plugin_classes as $plugin_fq_class_name) {
|
||||||
if ($plugin_method_id(
|
if ($plugin_fq_class_name::afterExpressionCheck(
|
||||||
$statements_checker,
|
$statements_checker,
|
||||||
$stmt,
|
$stmt,
|
||||||
$context,
|
$context,
|
||||||
|
@ -116,7 +116,7 @@ class StatementsChecker extends SourceChecker implements StatementsSource
|
|||||||
$original_context = clone $context;
|
$original_context = clone $context;
|
||||||
}
|
}
|
||||||
|
|
||||||
$plugin_method_ids = $codebase->config->after_statement_checks;
|
$plugin_classes = $codebase->config->after_statement_checks;
|
||||||
|
|
||||||
foreach ($stmts as $stmt) {
|
foreach ($stmts as $stmt) {
|
||||||
if ($has_returned && !($stmt instanceof PhpParser\Node\Stmt\Nop) &&
|
if ($has_returned && !($stmt instanceof PhpParser\Node\Stmt\Nop) &&
|
||||||
@ -479,12 +479,12 @@ class StatementsChecker extends SourceChecker implements StatementsSource
|
|||||||
//$has_returned = true;
|
//$has_returned = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($plugin_method_ids) {
|
if ($plugin_classes) {
|
||||||
$file_manipulations = [];
|
$file_manipulations = [];
|
||||||
$code_location = new CodeLocation($this->source, $stmt);
|
$code_location = new CodeLocation($this->source, $stmt);
|
||||||
|
|
||||||
foreach ($plugin_method_ids as $plugin_method_id) {
|
foreach ($plugin_classes as $plugin_fq_class_name) {
|
||||||
if ($plugin_method_id(
|
if ($plugin_fq_class_name::afterStatementCheck(
|
||||||
$this,
|
$this,
|
||||||
$stmt,
|
$stmt,
|
||||||
$context,
|
$context,
|
||||||
|
@ -608,23 +608,23 @@ class Config
|
|||||||
require_once($path);
|
require_once($path);
|
||||||
|
|
||||||
if ($codebase->methods->methodExists($fq_class_name . '::afterMethodCallCheck')) {
|
if ($codebase->methods->methodExists($fq_class_name . '::afterMethodCallCheck')) {
|
||||||
$this->after_method_checks[$fq_class_name] = $fq_class_name . '::afterMethodCallCheck';
|
$this->after_method_checks[$fq_class_name] = $fq_class_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($codebase->methods->methodExists($fq_class_name . '::afterExpressionCheck')) {
|
if ($codebase->methods->methodExists($fq_class_name . '::afterExpressionCheck')) {
|
||||||
$this->after_expression_checks[$fq_class_name] = $fq_class_name . '::afterExpressionCheck';
|
$this->after_expression_checks[$fq_class_name] = $fq_class_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($codebase->methods->methodExists($fq_class_name . '::afterStatementCheck')) {
|
if ($codebase->methods->methodExists($fq_class_name . '::afterStatementCheck')) {
|
||||||
$this->after_statement_checks[$fq_class_name] = $fq_class_name . '::afterStatementCheck';
|
$this->after_statement_checks[$fq_class_name] = $fq_class_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($codebase->methods->methodExists($fq_class_name . '::afterClassLikeExistsCheck')) {
|
if ($codebase->methods->methodExists($fq_class_name . '::afterClassLikeExistsCheck')) {
|
||||||
$this->after_classlike_exists_checks[$fq_class_name] = $fq_class_name . '::afterClassLikeExistsCheck';
|
$this->after_classlike_exists_checks[$fq_class_name] = $fq_class_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($codebase->methods->methodExists($fq_class_name . '::afterVisitClassLike')) {
|
if ($codebase->methods->methodExists($fq_class_name . '::afterVisitClassLike')) {
|
||||||
$this->after_visit_classlikes[$fq_class_name] = $fq_class_name . '::afterVisitClassLike';
|
$this->after_visit_classlikes[$fq_class_name] = $fq_class_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -656,8 +656,10 @@ class Config
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$fq_class_name = reset($declared_classes);
|
||||||
|
|
||||||
if (!$codebase->classExtends(
|
if (!$codebase->classExtends(
|
||||||
$declared_classes[0],
|
$fq_class_name,
|
||||||
$must_extend
|
$must_extend
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
@ -666,7 +668,7 @@ class Config
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $declared_classes[0];
|
return $fq_class_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,11 +121,11 @@ class FileReferenceProvider
|
|||||||
|
|
||||||
$file_classes = ClassLikeChecker::getClassesForFile($project_checker, $file);
|
$file_classes = ClassLikeChecker::getClassesForFile($project_checker, $file);
|
||||||
|
|
||||||
foreach ($file_classes as $file_class) {
|
foreach ($file_classes as $file_class_lc => $_) {
|
||||||
if (isset(self::$file_references_to_class[$file_class])) {
|
if (isset(self::$file_references_to_class[$file_class_lc])) {
|
||||||
$referenced_files = array_merge(
|
$referenced_files = array_merge(
|
||||||
$referenced_files,
|
$referenced_files,
|
||||||
array_keys(self::$file_references_to_class[$file_class])
|
array_keys(self::$file_references_to_class[$file_class_lc])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,11 +144,11 @@ class FileReferenceProvider
|
|||||||
|
|
||||||
$file_classes = ClassLikeChecker::getClassesForFile($project_checker, $file);
|
$file_classes = ClassLikeChecker::getClassesForFile($project_checker, $file);
|
||||||
|
|
||||||
foreach ($file_classes as $file_class) {
|
foreach ($file_classes as $file_class_lc => $_) {
|
||||||
if (isset(self::$files_inheriting_classes[$file_class])) {
|
if (isset(self::$files_inheriting_classes[$file_class_lc])) {
|
||||||
$referenced_files = array_merge(
|
$referenced_files = array_merge(
|
||||||
$referenced_files,
|
$referenced_files,
|
||||||
array_keys(self::$files_inheriting_classes[$file_class])
|
array_keys(self::$files_inheriting_classes[$file_class_lc])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ namespace Psalm\Storage;
|
|||||||
class FileStorage
|
class FileStorage
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var array<int, string>
|
* @var array<string, string>
|
||||||
*/
|
*/
|
||||||
public $classes_in_file = [];
|
public $classes_in_file = [];
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
|
|||||||
private $classlike_storages = [];
|
private $classlike_storages = [];
|
||||||
|
|
||||||
/** @var string[] */
|
/** @var string[] */
|
||||||
private $plugin_method_ids;
|
private $after_classlike_check_plugins;
|
||||||
|
|
||||||
public function __construct(Codebase $codebase, FileStorage $file_storage, FileScanner $file_scanner)
|
public function __construct(Codebase $codebase, FileStorage $file_storage, FileScanner $file_scanner)
|
||||||
{
|
{
|
||||||
@ -89,7 +89,7 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
|
|||||||
$this->config = $codebase->config;
|
$this->config = $codebase->config;
|
||||||
$this->aliases = $this->file_aliases = new Aliases();
|
$this->aliases = $this->file_aliases = new Aliases();
|
||||||
$this->file_storage = $file_storage;
|
$this->file_storage = $file_storage;
|
||||||
$this->plugin_method_ids = $this->config->after_visit_classlikes;
|
$this->after_classlike_check_plugins = $this->config->after_visit_classlikes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -155,7 +155,7 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
|
|||||||
} else {
|
} else {
|
||||||
$fq_classlike_name = ($this->aliases->namespace ? $this->aliases->namespace . '\\' : '') . $node->name;
|
$fq_classlike_name = ($this->aliases->namespace ? $this->aliases->namespace . '\\' : '') . $node->name;
|
||||||
$fq_classlike_name_lc = strtolower($fq_classlike_name);
|
$fq_classlike_name_lc = strtolower($fq_classlike_name);
|
||||||
$this->file_storage->classes_in_file[] = $fq_classlike_name_lc;
|
$this->file_storage->classes_in_file[$fq_classlike_name_lc] = $fq_classlike_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->fq_classlike_names[] = $fq_classlike_name;
|
$this->fq_classlike_names[] = $fq_classlike_name;
|
||||||
@ -483,11 +483,11 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
|
|||||||
|
|
||||||
$this->class_template_types = [];
|
$this->class_template_types = [];
|
||||||
|
|
||||||
if ($this->plugin_method_ids) {
|
if ($this->after_classlike_check_plugins) {
|
||||||
$file_manipulations = [];
|
$file_manipulations = [];
|
||||||
|
|
||||||
foreach ($this->plugin_method_ids as $plugin_method_id) {
|
foreach ($this->after_classlike_check_plugins as $plugin_fq_class_name) {
|
||||||
$plugin_method_id(
|
$plugin_fq_class_name::afterVisitClassLike(
|
||||||
$node,
|
$node,
|
||||||
$classlike_storage,
|
$classlike_storage,
|
||||||
$this->file_scanner,
|
$this->file_scanner,
|
||||||
|
Loading…
Reference in New Issue
Block a user