mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
Allow MissingParamType alteration to be done in multithreaded mode
This commit is contained in:
parent
534e4c034b
commit
a060da95bf
@ -172,7 +172,7 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer implements StatementsSou
|
||||
}
|
||||
}
|
||||
|
||||
public function getFunctionLikeAnalyzer(string $method_name) : FunctionLikeAnalyzer
|
||||
public function getFunctionLikeAnalyzer(string $method_name) : ?FunctionLikeAnalyzer
|
||||
{
|
||||
foreach ($this->class->stmts as $stmt) {
|
||||
if ($stmt instanceof PhpParser\Node\Stmt\ClassMethod &&
|
||||
@ -182,7 +182,7 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer implements StatementsSou
|
||||
}
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException('Should return a function analyzer');
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -340,12 +340,12 @@ class FileAnalyzer extends SourceAnalyzer implements StatementsSource
|
||||
}
|
||||
}
|
||||
|
||||
public function getFunctionLikeAnalyzer(string $method_id) : FunctionLikeAnalyzer
|
||||
public function getFunctionLikeAnalyzer(string $method_id) : ?FunctionLikeAnalyzer
|
||||
{
|
||||
list($fq_class_name, $method_name) = explode('::', $method_id);
|
||||
|
||||
if (!isset($this->class_analyzers_to_analyze[strtolower($fq_class_name)])) {
|
||||
throw new \UnexpectedValueException('Should not happen');
|
||||
return null;
|
||||
}
|
||||
|
||||
$class_analyzer_to_examine = $this->class_analyzers_to_analyze[strtolower($fq_class_name)];
|
||||
|
@ -953,7 +953,7 @@ class ProjectAnalyzer
|
||||
$file_analyzer->interface_analyzers_to_analyze = [];
|
||||
}
|
||||
|
||||
public function getFunctionLikeAnalyzer(string $method_id, string $file_path) : FunctionLikeAnalyzer
|
||||
public function getFunctionLikeAnalyzer(string $method_id, string $file_path) : ?FunctionLikeAnalyzer
|
||||
{
|
||||
$file_analyzer = new FileAnalyzer(
|
||||
$this,
|
||||
|
@ -2223,15 +2223,18 @@ class CallAnalyzer
|
||||
$declaring_method_id = $codebase->methods->getDeclaringMethodId($cased_method_id);
|
||||
|
||||
if ($declaring_method_id) {
|
||||
$method_storage = $codebase->methods->getStorage($declaring_method_id);
|
||||
$id_lc = strtolower($declaring_method_id);
|
||||
|
||||
if (!isset($method_storage->possible_param_types[$argument_offset])) {
|
||||
$method_storage->possible_param_types[$argument_offset] = clone $input_type;
|
||||
if (!isset($codebase->analyzer->possible_method_param_types[$id_lc][$argument_offset])) {
|
||||
$codebase->analyzer->possible_method_param_types[$id_lc][$argument_offset]
|
||||
= clone $input_type;
|
||||
} else {
|
||||
$method_storage->possible_param_types[$argument_offset] = Type::combineUnionTypes(
|
||||
$method_storage->possible_param_types[$argument_offset],
|
||||
clone $input_type
|
||||
);
|
||||
$codebase->analyzer->possible_method_param_types[$id_lc][$argument_offset]
|
||||
= Type::combineUnionTypes(
|
||||
$codebase->analyzer->possible_method_param_types[$id_lc][$argument_offset],
|
||||
clone $input_type,
|
||||
$codebase
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,8 @@ use Psalm\Progress\Progress;
|
||||
* >,
|
||||
* class_locations: array<string, array<int, \Psalm\CodeLocation>>,
|
||||
* class_method_locations: array<string, array<int, \Psalm\CodeLocation>>,
|
||||
* class_property_locations: array<string, array<int, \Psalm\CodeLocation>>
|
||||
* class_property_locations: array<string, array<int, \Psalm\CodeLocation>>,
|
||||
* possible_method_param_types: array<string, array<int, \Psalm\Type\Union>>
|
||||
* }
|
||||
*/
|
||||
|
||||
@ -135,6 +136,11 @@ class Analyzer
|
||||
*/
|
||||
private $type_map = [];
|
||||
|
||||
/**
|
||||
* @var array<string, array<int, \Psalm\Type\Union>>
|
||||
*/
|
||||
public $possible_method_param_types = [];
|
||||
|
||||
public function __construct(
|
||||
Config $config,
|
||||
FileProvider $file_provider,
|
||||
@ -299,6 +305,7 @@ class Analyzer
|
||||
'class_locations' => $file_reference_provider->getAllClassLocations(),
|
||||
'class_method_locations' => $file_reference_provider->getAllClassMethodLocations(),
|
||||
'class_property_locations' => $file_reference_provider->getAllClassPropertyLocations(),
|
||||
'possible_method_param_types' => $analyzer->getPossibleMethodParamTypes(),
|
||||
];
|
||||
},
|
||||
$task_done_closure
|
||||
@ -363,6 +370,26 @@ class Analyzer
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($pool_data['possible_method_param_types'] as $declaring_method_id => $possible_param_types) {
|
||||
if (!isset($this->possible_method_param_types[$declaring_method_id])) {
|
||||
$this->possible_method_param_types[$declaring_method_id] = $possible_param_types;
|
||||
} else {
|
||||
foreach ($possible_param_types as $offset => $possible_param_type) {
|
||||
if (!isset($this->possible_method_param_types[$declaring_method_id][$offset])) {
|
||||
$this->possible_method_param_types[$declaring_method_id][$offset]
|
||||
= $possible_param_type;
|
||||
} else {
|
||||
$this->possible_method_param_types[$declaring_method_id][$offset]
|
||||
= \Psalm\Type::combineUnionTypes(
|
||||
$this->possible_method_param_types[$declaring_method_id][$offset],
|
||||
$possible_param_type,
|
||||
$codebase
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($pool_data['file_manipulations'] as $file_path => $manipulations) {
|
||||
FileManipulationBuffer::add($file_path, $manipulations);
|
||||
}
|
||||
@ -1223,6 +1250,14 @@ class Analyzer
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array<int, \Psalm\Type\Union>>
|
||||
*/
|
||||
public function getPossibleMethodParamTypes()
|
||||
{
|
||||
return $this->possible_method_param_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $file_path
|
||||
* @param string $method_id
|
||||
|
@ -929,30 +929,43 @@ class ClassLikes
|
||||
} else {
|
||||
if ($codebase->alter_code
|
||||
&& isset($project_analyzer->getIssuesToFix()['MissingParamType'])
|
||||
&& isset($codebase->analyzer->possible_method_param_types[strtolower($method_id)])
|
||||
) {
|
||||
if ($method_storage->possible_param_types && $method_storage->location) {
|
||||
if ($method_storage->location) {
|
||||
$function_analyzer = $project_analyzer->getFunctionLikeAnalyzer(
|
||||
$method_id,
|
||||
$method_storage->location->file_path
|
||||
);
|
||||
|
||||
foreach ($method_storage->possible_param_types as $offset => $possible_type) {
|
||||
if (!isset($method_storage->params[$offset])) {
|
||||
continue;
|
||||
$possible_param_types
|
||||
= $codebase->analyzer->possible_method_param_types[strtolower($method_id)];
|
||||
|
||||
if ($function_analyzer && $possible_param_types) {
|
||||
foreach ($possible_param_types as $offset => $possible_type) {
|
||||
if (!isset($method_storage->params[$offset])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$param_name = $method_storage->params[$offset]->name;
|
||||
|
||||
if ($possible_type->hasMixed() || $possible_type->isNull()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($method_storage->params[$offset]->default_type) {
|
||||
$possible_type = \Psalm\Type::combineUnionTypes(
|
||||
$possible_type,
|
||||
$method_storage->params[$offset]->default_type
|
||||
);
|
||||
}
|
||||
|
||||
$function_analyzer->addOrUpdateParamType(
|
||||
$project_analyzer,
|
||||
$param_name,
|
||||
$possible_type,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
$param_name = $method_storage->params[$offset]->name;
|
||||
|
||||
if ($possible_type->hasMixed() || $possible_type->isNull()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$function_analyzer->addOrUpdateParamType(
|
||||
$project_analyzer,
|
||||
$param_name,
|
||||
$possible_type,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,11 +169,6 @@ class FunctionLikeStorage
|
||||
*/
|
||||
public $unused_docblock_params;
|
||||
|
||||
/**
|
||||
* @var array<int, Type\Union>|null
|
||||
*/
|
||||
public $possible_param_types;
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
$symbol_text = 'function ' . $this->cased_name . '(' . implode(
|
||||
|
@ -368,19 +368,15 @@ if ($config->find_unused_code) {
|
||||
$find_unused_code = true;
|
||||
}
|
||||
|
||||
foreach ($keyed_issues as $issue_name => $_) {
|
||||
// MissingParamType requires the scanning of all files to inform possible params
|
||||
if (strpos($issue_name, 'Unused') !== false || $issue_name === 'MissingParamType') {
|
||||
$find_unused_code = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($find_unused_code) {
|
||||
$project_analyzer->getCodebase()->reportUnusedCode();
|
||||
} else {
|
||||
foreach ($keyed_issues as $issue_name => $_) {
|
||||
if (strpos($issue_name, 'Unused') !== false) {
|
||||
die(
|
||||
'Error: Psalm can only fix issue '
|
||||
. $issue_name
|
||||
. ' if you enable unused code detection with --find-unused-code'
|
||||
. PHP_EOL
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$project_analyzer->alterCodeAfterCompletion(
|
||||
|
@ -85,6 +85,26 @@ class ParamTypeManipulationTest extends FileManipulationTest
|
||||
['MissingParamType'],
|
||||
true,
|
||||
],
|
||||
'noBoolParamTypeWithDefault' => [
|
||||
'<?php
|
||||
class C {
|
||||
public function fooFoo($a = true): void {}
|
||||
}
|
||||
|
||||
(new C)->fooFoo(false);',
|
||||
'<?php
|
||||
class C {
|
||||
/**
|
||||
* @param bool $a
|
||||
*/
|
||||
public function fooFoo($a = true): void {}
|
||||
}
|
||||
|
||||
(new C)->fooFoo(false);',
|
||||
'7.1',
|
||||
['MissingParamType'],
|
||||
true,
|
||||
],
|
||||
'noStringParamTypeParent' => [
|
||||
'<?php
|
||||
class C {
|
||||
|
Loading…
Reference in New Issue
Block a user