mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
Convert InvalidScalarArgument to InvalidArgument when declare(strict_types=1) is set
This commit is contained in:
parent
ba87eb069c
commit
1037485a60
@ -733,6 +733,7 @@ class TypeChecker
|
||||
|
||||
if ($input_type_part instanceof Scalar) {
|
||||
if ($container_type_part instanceof Scalar
|
||||
&& !$container_type_part->strict
|
||||
&& !$container_type_part instanceof TLiteralInt
|
||||
&& !$container_type_part instanceof TLiteralString
|
||||
&& !$container_type_part instanceof TLiteralFloat
|
||||
|
@ -76,12 +76,17 @@ abstract class Type
|
||||
* @param string $type_string
|
||||
* @param bool $php_compatible
|
||||
* @param array<string, string> $template_type_names
|
||||
* @param bool $strict_types
|
||||
*
|
||||
* @return Union
|
||||
*/
|
||||
public static function parseString($type_string, $php_compatible = false, array $template_type_names = [])
|
||||
{
|
||||
return self::parseTokens(self::tokenize($type_string), $php_compatible, $template_type_names);
|
||||
public static function parseString(
|
||||
$type_string,
|
||||
$php_compatible = false,
|
||||
array $template_type_names = [],
|
||||
$strict_types = false
|
||||
) {
|
||||
return self::parseTokens(self::tokenize($type_string), $php_compatible, $template_type_names, $strict_types);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,11 +95,16 @@ abstract class Type
|
||||
* @param array<int, string> $type_tokens
|
||||
* @param bool $php_compatible
|
||||
* @param array<string, string> $template_type_names
|
||||
* @param bool $strict_types
|
||||
*
|
||||
* @return Union
|
||||
*/
|
||||
public static function parseTokens(array $type_tokens, $php_compatible = false, array $template_type_names = [])
|
||||
{
|
||||
public static function parseTokens(
|
||||
array $type_tokens,
|
||||
$php_compatible = false,
|
||||
array $template_type_names = [],
|
||||
$strict_types = false
|
||||
) {
|
||||
if (count($type_tokens) === 1) {
|
||||
$only_token = $type_tokens[0];
|
||||
|
||||
@ -105,7 +115,7 @@ abstract class Type
|
||||
|
||||
$only_token = self::fixScalarTerms($only_token, $php_compatible);
|
||||
|
||||
return new Union([Atomic::create($only_token, $php_compatible, $template_type_names)]);
|
||||
return new Union([Atomic::create($only_token, $php_compatible, $template_type_names, $strict_types)]);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -54,27 +54,56 @@ abstract class Atomic
|
||||
* @param string $value
|
||||
* @param bool $php_compatible
|
||||
* @param array<string, string> $template_type_names
|
||||
* @param bool $strict_types
|
||||
*
|
||||
* @return Atomic
|
||||
*/
|
||||
public static function create($value, $php_compatible = false, array $template_type_names = [])
|
||||
{
|
||||
public static function create(
|
||||
$value,
|
||||
$php_compatible = false,
|
||||
array $template_type_names = [],
|
||||
$strict_types = false
|
||||
) {
|
||||
switch ($value) {
|
||||
case 'int':
|
||||
return new TInt();
|
||||
$t = new TInt();
|
||||
|
||||
if ($strict_types) {
|
||||
$t->strict = true;
|
||||
}
|
||||
|
||||
return $t;
|
||||
|
||||
case 'float':
|
||||
$t = new TFloat();
|
||||
|
||||
if ($strict_types) {
|
||||
$t->strict = true;
|
||||
}
|
||||
|
||||
return $t;
|
||||
|
||||
case 'string':
|
||||
$t = new TString();
|
||||
|
||||
if ($strict_types) {
|
||||
$t->strict = true;
|
||||
}
|
||||
|
||||
return $t;
|
||||
|
||||
case 'bool':
|
||||
$t = new TBool();
|
||||
|
||||
if ($strict_types) {
|
||||
$t->strict = true;
|
||||
}
|
||||
|
||||
return $t;
|
||||
|
||||
case 'void':
|
||||
return new TVoid();
|
||||
|
||||
case 'float':
|
||||
return new TFloat();
|
||||
|
||||
case 'string':
|
||||
return new TString();
|
||||
|
||||
case 'bool':
|
||||
return new TBool();
|
||||
|
||||
case 'object':
|
||||
return new TObject();
|
||||
|
||||
|
@ -3,6 +3,9 @@ namespace Psalm\Type\Atomic;
|
||||
|
||||
abstract class Scalar extends \Psalm\Type\Atomic
|
||||
{
|
||||
/** @var true|null */
|
||||
public $strict;
|
||||
|
||||
/**
|
||||
* @param string|null $namespace
|
||||
* @param array<string> $aliased_classes
|
||||
|
@ -83,6 +83,9 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
|
||||
/** @var string[] */
|
||||
private $after_classlike_check_plugins;
|
||||
|
||||
/** @var bool */
|
||||
private $strict_types = false;
|
||||
|
||||
/**
|
||||
* @var array<string, array<int, string>>
|
||||
*/
|
||||
@ -450,6 +453,15 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
|
||||
if ($function_like_storage) {
|
||||
$function_like_storage->has_yield = true;
|
||||
}
|
||||
} elseif ($node instanceof PhpParser\Node\Stmt\Declare_) {
|
||||
foreach ($node->declares as $declaration) {
|
||||
if ((string) $declaration->key === 'strict_types'
|
||||
&& $declaration->value instanceof PhpParser\Node\Scalar\LNumber
|
||||
&& $declaration->value->value === 1
|
||||
) {
|
||||
$this->strict_types = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1418,11 +1430,11 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
|
||||
}
|
||||
|
||||
if ($param_type_string) {
|
||||
if ($is_nullable) {
|
||||
$param_type_string .= '|null';
|
||||
}
|
||||
$param_type = Type::parseString($param_type_string, true, [], $this->strict_types);
|
||||
|
||||
$param_type = Type::parseString($param_type_string, true);
|
||||
if ($is_nullable) {
|
||||
$param_type->addType(new Type\Atomic\TNull);
|
||||
}
|
||||
|
||||
if ($param->variadic) {
|
||||
$param_type = new Type\Union([
|
||||
|
@ -956,6 +956,12 @@ class FunctionCallTest extends TestCase
|
||||
fooFoo("string");',
|
||||
'error_message' => 'InvalidScalarArgument',
|
||||
],
|
||||
'invalidArgumentWithDeclareStrictTypes' => [
|
||||
'<?php declare(strict_types=1);
|
||||
function fooFoo(int $a): void {}
|
||||
fooFoo("string");',
|
||||
'error_message' => 'InvalidArgument',
|
||||
],
|
||||
'mixedArgument' => [
|
||||
'<?php
|
||||
function fooFoo(int $a): void {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user