1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

Allow updating of params

This commit is contained in:
Matthew Brown 2018-01-07 10:23:02 -05:00
parent 5bae869dc6
commit 0e67aae21b
4 changed files with 155 additions and 2 deletions

View File

@ -380,7 +380,7 @@ class CommentChecker
*
* @return array<string>
*/
protected static function splitDocLine($return_block)
public static function splitDocLine($return_block)
{
$brackets = '';

View File

@ -305,6 +305,14 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
$signature_type
)
) {
if ($project_checker->alter_code
&& isset($project_checker->getIssuesToFix()['MismatchingDocblockParamType'])
) {
$this->addOrUpdateParamType($project_checker, $function_param->name, $signature_type, true);
return null;
}
if (IssueBuffer::accepts(
new MismatchingDocblockParamType(
'Parameter $' . $function_param->name . ' has wrong type \'' . $param_type .
@ -1423,6 +1431,47 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
return null;
}
/**
* @param string $param_name
* @param bool $docblock_only
*
* @return void
*/
private function addOrUpdateParamType(
ProjectChecker $project_checker,
$param_name,
Type\Union $inferred_return_type,
$docblock_only = false
) {
$manipulator = FunctionDocblockManipulator::getForFunction(
$project_checker,
$this->source->getFilePath(),
$this->getMethodId(),
$this->function
);
$manipulator->setParamType(
$param_name,
!$docblock_only && $project_checker->php_major_version >= 7
? $inferred_return_type->toPhpString(
$this->source->getAliasedClassesFlipped(),
$this->source->getFQCLN(),
$project_checker->php_major_version,
$project_checker->php_minor_version
) : null,
$inferred_return_type->toNamespacedString(
$this->source->getAliasedClassesFlipped(),
$this->source->getFQCLN(),
false
),
$inferred_return_type->toNamespacedString(
$this->source->getAliasedClassesFlipped(),
$this->source->getFQCLN(),
true
),
$inferred_return_type->canBeFullyExpressedInPhp()
);
}
/**
* @param bool $docblock_only
*

View File

@ -50,6 +50,27 @@ class FunctionDocblockManipulator
/** @var ?string */
private $new_psalm_return_type;
/** @var array<string, int> */
private $param_typehint_area_starts = [];
/** @var array<string, int> */
private $param_typehint_starts = [];
/** @var array<string, int> */
private $param_typehint_ends = [];
/** @var array<string, string> */
private $new_php_param_types = [];
/** @var array<string, bool> */
private $param_type_is_php_compatible = [];
/** @var array<string, string> */
private $new_phpdoc_param_types = [];
/** @var array<string, string> */
private $new_psalm_param_types = [];
/** @var string */
private $indentation;
@ -92,6 +113,8 @@ class FunctionDocblockManipulator
$file_contents = $project_checker->getFileContents($file_path);
$last_arg_position = $stmt->params
? (int) $stmt->params[count($stmt->params) - 1]->getAttribute('endFilePos')
: null;
@ -158,7 +181,7 @@ class FunctionDocblockManipulator
}
/**
* Sets the new docblock return type
* Sets the new return type
*
* @param ?string $php_type
* @param string $new_type
@ -177,6 +200,30 @@ class FunctionDocblockManipulator
$this->return_type_is_php_compatible = $is_php_compatible;
}
/**
* Sets a new param type
*
* @param string $param_name
* @param ?string $php_type
* @param string $new_type
* @param string $phpdoc_type
* @param bool $is_php_compatible
*
* @return void
*/
public function setParamType($param_name, $php_type, $new_type, $phpdoc_type, $is_php_compatible)
{
$new_type = str_replace(['<mixed, mixed>', '<empty, empty>'], '', $new_type);
if ($php_type) {
$this->new_php_param_types[$param_name] = $php_type;
}
$this->new_phpdoc_param_types[$param_name] = $phpdoc_type;
$this->new_psalm_param_types[$param_name] = $new_type;
$this->param_type_is_php_compatible[$param_name] = $is_php_compatible;
}
/**
* Gets a new docblock given the existing docblock, if one exists, and the updated return types
* and/or parameters
@ -193,6 +240,27 @@ class FunctionDocblockManipulator
$parsed_docblock = ['description' => ''];
}
foreach ($this->new_phpdoc_param_types as $param_name => $phpdoc_type) {
$found_in_params = false;
$new_param_block = $phpdoc_type . ' ' . '$' . $param_name;
if (isset($parsed_docblock['specials']['param'])) {
foreach ($parsed_docblock['specials']['param'] as &$param_block) {
$doc_parts = CommentChecker::splitDocLine($param_block);
if ($doc_parts[1] === '$' . $param_name) {
$param_block = $new_param_block;
$found_in_params = true;
break;
}
}
}
if (!$found_in_params) {
$parsed_docblock['specials']['params'][] = $new_param_block;
}
}
if ($this->new_phpdoc_return_type) {
$parsed_docblock['specials']['return'] = [$this->new_phpdoc_return_type];
}

View File

@ -257,6 +257,42 @@ class FileManipulationTest extends TestCase
'7.0',
['InvalidReturnType'],
],
'fixMismatchingDocblockReturnType70' => [
'<?php
/**
* @return int
*/
function foo() : string {
return "hello";
}',
'<?php
/**
* @return string
*/
function foo() : string {
return "hello";
}',
'7.0',
['MismatchingDocblockReturnType'],
],
'fixMismatchingDocblockParamType70' => [
'<?php
/**
* @param int $s
*/
function foo(string $s) : string {
return "hello";
}',
'<?php
/**
* @param string $s
*/
function foo(string $s) : string {
return "hello";
}',
'7.0',
['MismatchingDocblockParamType'],
],
'useUnqualifierPlugin' => [
'<?php
namespace A\B\C {