1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-21 21:31:13 +01:00

Allow docblock types to be merged with param default ones

This commit is contained in:
Matt Brown 2018-06-07 12:23:10 -04:00
parent fb3bc2661e
commit f030f4f40d
5 changed files with 92 additions and 2 deletions

View File

@ -38,6 +38,7 @@
<xs:attribute name="usePhpDocMethodsWithoutMagicCall" type="xs:string" />
<xs:attribute name="memoizeMethodCallResults" type="xs:string" />
<xs:attribute name="hoistConstants" type="xs:string" />
<xs:attribute name="addParamDefaultToDocblockType" type="xs:string" />
</xs:complexType>
<xs:complexType name="ProjectFilesType">

View File

@ -213,6 +213,11 @@ class Config
*/
public $hoist_constants = false;
/**
* @var bool
*/
public $add_param_default_to_docblock_type = false;
/**
* @var string[]
*/
@ -526,6 +531,11 @@ class Config
$config->hoist_constants = $attribute_text === 'true' || $attribute_text === '1';
}
if (isset($config_xml['addParamDefaultToDocblockType'])) {
$attribute_text = (string) $config_xml['addParamDefaultToDocblockType'];
$config->add_param_default_to_docblock_type = $attribute_text === 'true' || $attribute_text === '1';
}
if (isset($config_xml->projectFiles)) {
$config->project_files = ProjectFileFilter::loadFromXMLElement($config_xml->projectFiles, $base_dir, true);
}

View File

@ -36,6 +36,11 @@ class FunctionLikeParameter
*/
public $is_nullable;
/**
* @var Type\Union|null
*/
public $default_type;
/**
* @var CodeLocation|null
*/
@ -64,6 +69,7 @@ class FunctionLikeParameter
* @param bool $is_optional
* @param bool $is_nullable
* @param bool $is_variadic
* @param Type\Union|null $default_type
*/
public function __construct(
$name,
@ -73,7 +79,8 @@ class FunctionLikeParameter
CodeLocation $type_location = null,
$is_optional = true,
$is_nullable = false,
$is_variadic = false
$is_variadic = false,
$default_type = null
) {
$this->name = $name;
$this->by_ref = $by_ref;
@ -85,6 +92,7 @@ class FunctionLikeParameter
$this->location = $location;
$this->type_location = $type_location;
$this->signature_type_location = $type_location;
$this->default_type = $default_type;
}
public function __toString()

View File

@ -1306,7 +1306,8 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
: null,
$is_optional,
$is_nullable,
$param->variadic
$param->variadic,
$param->default ? StatementsChecker::getSimpleType($param->default, $this) : null
);
}
@ -1410,6 +1411,14 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
$new_param_type->addType(new Type\Atomic\TNull());
}
if ($this->config->add_param_default_to_docblock_type
&& $storage_param->default_type
&& !$storage_param->default_type->isMixed()
&& (!$storage_param->type || !$storage_param->type->isMixed())
) {
$new_param_type = Type::combineUnionTypes($new_param_type, $storage_param->default_type);
}
$storage_param->type = $new_param_type;
$storage_param->type_location = $code_location;
continue;

View File

@ -207,6 +207,68 @@ class AnnotationTest extends TestCase
$this->analyzeFile('somefile.php', new Context());
}
/**
* @expectedException \Psalm\Exception\CodeException
* @expectedExceptionMessage InvalidParamDefault
*
* @return void
*/
public function testInvalidParamDefault()
{
$this->addFile(
'somefile.php',
'<?php
/**
* @param array $arr
* @return void
*/
function foo($arr = false) {}'
);
$this->analyzeFile('somefile.php', new Context());
}
/**
* @return void
*/
public function testInvalidParamDefaultButAllowedInConfig()
{
Config::getInstance()->add_param_default_to_docblock_type = true;
$this->addFile(
'somefile.php',
'<?php
/**
* @param array $arr
* @return void
*/
function foo($arr = false) {}
foo(false);
foo(["hello"]);'
);
$this->analyzeFile('somefile.php', new Context());
}
/**
* @expectedException \Psalm\Exception\CodeException
* @expectedExceptionMessage InvalidParamDefault
*
* @return void
*/
public function testInvalidTypehintParamDefaultButAllowedInConfig()
{
Config::getInstance()->add_param_default_to_docblock_type = true;
$this->addFile(
'somefile.php',
'<?php
function foo(array $arr = false) : void {}'
);
$this->analyzeFile('somefile.php', new Context());
}
/**
* @return void
*/