1
0
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:
Matthew Brown 2018-02-11 22:49:19 -05:00
parent f159cd5146
commit affcaebc3d
9 changed files with 75 additions and 35 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 = [];

View 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,