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

Merge pull request #6535 from orklah/SA

Improvements
This commit is contained in:
orklah 2021-09-25 20:16:38 +02:00 committed by GitHub
commit afbda6d0f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 103 additions and 133 deletions

View File

@ -5,6 +5,7 @@ use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
use Psalm\Internal\Scanner\FileScanner;
use SimpleXMLElement;
use function class_exists;
use function reset;
class FileBasedPluginAdapter implements Plugin\PluginEntryPointInterface
@ -39,6 +40,8 @@ class FileBasedPluginAdapter implements Plugin\PluginEntryPointInterface
/** @psalm-suppress UnresolvableInclude */
require_once($this->path);
\assert(class_exists($fq_class_name));
$registration->registerHooksFromClass($fq_class_name);
}

View File

@ -106,8 +106,8 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer
public function __destruct()
{
$this->source = null;
$this->file_analyzer = null;
unset($this->source);
unset($this->file_analyzer);
}
public function getMethodMutations(

View File

@ -662,7 +662,6 @@ class FileAnalyzer extends SourceAnalyzer
public function clearSourceBeforeDestruction() : void
{
/** @psalm-suppress PossiblyNullPropertyAssignmentValue */
$this->source = null;
unset($this->source);
}
}

View File

@ -18,7 +18,7 @@ abstract class SourceAnalyzer implements StatementsSource
public function __destruct()
{
$this->source = null;
unset($this->source);
}
public function getAliases(): Aliases

View File

@ -98,10 +98,9 @@ class SwitchCaseAnalyzer
$case_context->inside_conditional = true;
if (ExpressionAnalyzer::analyze($statements_analyzer, $case->cond, $case_context) === false) {
/** @psalm-suppress PossiblyNullPropertyAssignmentValue */
$case_scope->parent_context = null;
$case_context->case_scope = null;
$case_context->parent_context = null;
unset($case_scope->parent_context);
unset($case_context->case_scope);
unset($case_context->parent_context);
return false;
}
@ -273,10 +272,9 @@ class SwitchCaseAnalyzer
$switch_scope->leftover_statements = [$case_if_stmt];
}
/** @psalm-suppress PossiblyNullPropertyAssignmentValue */
$case_scope->parent_context = null;
$case_context->case_scope = null;
$case_context->parent_context = null;
unset($case_scope->parent_context);
unset($case_context->case_scope);
unset($case_context->parent_context);
$statements_analyzer->node_data = $old_node_data;
@ -500,10 +498,9 @@ class SwitchCaseAnalyzer
$case_exit_type,
$switch_scope
) === false) {
/** @psalm-suppress PossiblyNullPropertyAssignmentValue */
$case_scope->parent_context = null;
$case_context->case_scope = null;
$case_context->parent_context = null;
unset($case_scope->parent_context);
unset($case_context->case_scope);
unset($case_context->parent_context);
return false;
}
@ -558,10 +555,9 @@ class SwitchCaseAnalyzer
}
}
/** @psalm-suppress PossiblyNullPropertyAssignmentValue */
$case_scope->parent_context = null;
$case_context->case_scope = null;
$case_context->parent_context = null;
unset($case_scope->parent_context);
unset($case_context->case_scope);
unset($case_context->parent_context);
return null;
}

View File

@ -58,7 +58,7 @@ class TryAnalyzer
$existing_thrown_exceptions = $context->possibly_thrown_exceptions;
/**
* @var array<string, array<array-key, CodeLocation>>
* @var array<string, array<array-key, CodeLocation>> $context->possibly_thrown_exceptions
*/
$context->possibly_thrown_exceptions = [];
@ -270,9 +270,6 @@ class TryAnalyzer
}
}
/**
* @var array<string, array<array-key, CodeLocation>>
*/
$catch_context->possibly_thrown_exceptions = [];
}

View File

@ -55,7 +55,7 @@ class AndAnalyzer
$left_context->referenced_var_ids = [];
$left_context->assigned_var_ids = [];
/** @var list<string> */
/** @var list<string> $left_context->reconciled_expression_clauses */
$left_context->reconciled_expression_clauses = [];
if (ExpressionAnalyzer::analyze($statements_analyzer, $stmt->left, $left_context) === false) {

View File

@ -289,8 +289,8 @@ class ArithmeticOpAnalyzer
}
/**
* @param string[] &$invalid_left_messages
* @param string[] &$invalid_right_messages
* @param string[] $invalid_left_messages
* @param string[] $invalid_right_messages
*/
private static function analyzeOperands(
?StatementsSource $statements_source,

View File

@ -36,7 +36,7 @@ use function strlen;
class ConcatAnalyzer
{
/**
* @param Type\Union|null &$result_type
* @param Type\Union|null $result_type
*/
public static function analyze(
StatementsAnalyzer $statements_analyzer,

View File

@ -39,10 +39,7 @@ use Psalm\IssueBuffer;
use Psalm\Plugin\EventHandler\Event\AddRemoveTaintsEvent;
use Psalm\Storage\FunctionLikeParameter;
use Psalm\Type;
use Psalm\Type\Atomic\TArray;
use Psalm\Type\Atomic\TCallable;
use Psalm\Type\Atomic\TClassString;
use Psalm\Type\Atomic\TList;
use Psalm\Type\Atomic;
use function array_merge;
use function count;
@ -101,11 +98,11 @@ class ArgumentAnalyzer
) {
/**
* @psalm-suppress PossiblyUndefinedStringArrayOffset
* @var TList|TArray
* @var Atomic\TList|Atomic\TArray
*/
$array_type = $param_type->getAtomicTypes()['array'];
if ($array_type instanceof TList) {
if ($array_type instanceof Atomic\TList) {
$param_type = $array_type->type_param;
} else {
$param_type = $array_type->type_params[1];
@ -313,20 +310,20 @@ class ArgumentAnalyzer
$arg_type_param = null;
foreach ($arg_type->getAtomicTypes() as $arg_atomic_type) {
if ($arg_atomic_type instanceof Type\Atomic\TArray
|| $arg_atomic_type instanceof Type\Atomic\TList
|| $arg_atomic_type instanceof Type\Atomic\TKeyedArray
if ($arg_atomic_type instanceof Atomic\TArray
|| $arg_atomic_type instanceof Atomic\TList
|| $arg_atomic_type instanceof Atomic\TKeyedArray
) {
if ($arg_atomic_type instanceof Type\Atomic\TKeyedArray) {
if ($arg_atomic_type instanceof Atomic\TKeyedArray) {
$arg_type_param = $arg_atomic_type->getGenericValueType();
} elseif ($arg_atomic_type instanceof Type\Atomic\TList) {
} elseif ($arg_atomic_type instanceof Atomic\TList) {
$arg_type_param = $arg_atomic_type->type_param;
} else {
$arg_type_param = $arg_atomic_type->type_params[1];
}
} elseif ($arg_atomic_type instanceof Type\Atomic\TIterable) {
} elseif ($arg_atomic_type instanceof Atomic\TIterable) {
$arg_type_param = $arg_atomic_type->type_params[1];
} elseif ($arg_atomic_type instanceof Type\Atomic\TNamedObject) {
} elseif ($arg_atomic_type instanceof Atomic\TNamedObject) {
ForeachAnalyzer::getKeyValueParamsForTraversableObject(
$arg_atomic_type,
$codebase,
@ -457,12 +454,12 @@ class ArgumentAnalyzer
if ($arg_type->hasArray()) {
/**
* @psalm-suppress PossiblyUndefinedStringArrayOffset
* @var Type\Atomic\TArray|Type\Atomic\TList|Type\Atomic\TKeyedArray|Type\Atomic\TClassStringMap
* @var Atomic\TArray|Atomic\TList|Atomic\TKeyedArray|Atomic\TClassStringMap
*/
$unpacked_atomic_array = $arg_type->getAtomicTypes()['array'];
$arg_key_allowed = true;
if ($unpacked_atomic_array instanceof Type\Atomic\TKeyedArray) {
if ($unpacked_atomic_array instanceof Atomic\TKeyedArray) {
if (!$allow_named_args && !$unpacked_atomic_array->getGenericKeyType()->isInt()) {
$arg_key_allowed = false;
}
@ -493,9 +490,9 @@ class ArgumentAnalyzer
} else {
$arg_type = Type::getMixed();
}
} elseif ($unpacked_atomic_array instanceof Type\Atomic\TList) {
} elseif ($unpacked_atomic_array instanceof Atomic\TList) {
$arg_type = $unpacked_atomic_array->type_param;
} elseif ($unpacked_atomic_array instanceof Type\Atomic\TClassStringMap) {
} elseif ($unpacked_atomic_array instanceof Atomic\TClassStringMap) {
$arg_type = Type::getMixed();
} else {
if (!$allow_named_args && !$unpacked_atomic_array->type_params[0]->isInt()) {
@ -653,8 +650,7 @@ class ArgumentAnalyzer
}
/**
* @param Type\Atomic\TKeyedArray|Type\Atomic\TArray|Type\Atomic\TList|Type\Atomic\TClassStringMap
* $unpacked_atomic_array
* @param Atomic\TKeyedArray|Atomic\TArray|Atomic\TList|Atomic\TClassStringMap $unpacked_atomic_array
* @return null|false
*/
public static function verifyType(
@ -835,7 +831,7 @@ class ArgumentAnalyzer
// we do this replacement early because later we don't have access to the
// $statements_analyzer, which is necessary to understand string function names
foreach ($input_type->getAtomicTypes() as $key => $atomic_type) {
if (!$atomic_type instanceof Type\Atomic\TLiteralString
if (!$atomic_type instanceof Atomic\TLiteralString
|| \Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($atomic_type->value)
) {
continue;
@ -902,7 +898,7 @@ class ArgumentAnalyzer
$potential_method_ids = [];
foreach ($input_type->getAtomicTypes() as $input_type_part) {
if ($input_type_part instanceof Type\Atomic\TKeyedArray) {
if ($input_type_part instanceof Atomic\TKeyedArray) {
$potential_method_id = CallableTypeComparator::getCallableMethodIdFromTKeyedArray(
$input_type_part,
$codebase,
@ -913,7 +909,7 @@ class ArgumentAnalyzer
if ($potential_method_id && $potential_method_id !== 'not-callable') {
$potential_method_ids[] = $potential_method_id;
}
} elseif ($input_type_part instanceof Type\Atomic\TLiteralString
} elseif ($input_type_part instanceof Atomic\TLiteralString
&& strpos($input_type_part->value, '::')
) {
$parts = explode('::', $input_type_part->value);
@ -1183,7 +1179,7 @@ class ArgumentAnalyzer
$codebase = $statements_analyzer->getCodebase();
foreach ($param_type->getAtomicTypes() as $param_type_part) {
if ($param_type_part instanceof TClassString
if ($param_type_part instanceof Atomic\TClassString
&& $input_expr instanceof PhpParser\Node\Scalar\String_
&& $param_type->isSingle()
) {
@ -1199,11 +1195,11 @@ class ArgumentAnalyzer
) {
return;
}
} elseif ($param_type_part instanceof TArray
} elseif ($param_type_part instanceof Atomic\TArray
&& $input_expr instanceof PhpParser\Node\Expr\Array_
) {
foreach ($param_type_part->type_params[1]->getAtomicTypes() as $param_array_type_part) {
if ($param_array_type_part instanceof TClassString) {
if ($param_array_type_part instanceof Atomic\TClassString) {
foreach ($input_expr->items as $item) {
if ($item && $item->value instanceof PhpParser\Node\Scalar\String_) {
if (ClassLikeAnalyzer::checkFullyQualifiedClassLikeName(
@ -1222,7 +1218,7 @@ class ArgumentAnalyzer
}
}
}
} elseif ($param_type_part instanceof TCallable) {
} elseif ($param_type_part instanceof Atomic\TCallable) {
$can_be_callable_like_array = false;
if ($param_type->hasArray()) {
/**
@ -1231,11 +1227,11 @@ class ArgumentAnalyzer
$param_array_type = $param_type->getAtomicTypes()['array'];
$row_type = null;
if ($param_array_type instanceof TList) {
if ($param_array_type instanceof Atomic\TList) {
$row_type = $param_array_type->type_param;
} elseif ($param_array_type instanceof TArray) {
} elseif ($param_array_type instanceof Atomic\TArray) {
$row_type = $param_array_type->type_params[1];
} elseif ($param_array_type instanceof Type\Atomic\TKeyedArray) {
} elseif ($param_array_type instanceof Atomic\TKeyedArray) {
$row_type = $param_array_type->getGenericArrayType()->type_params[1];
}
@ -1350,8 +1346,7 @@ class ArgumentAnalyzer
}
/**
* @param Type\Atomic\TKeyedArray|Type\Atomic\TArray|Type\Atomic\TList|Type\Atomic\TClassStringMap
* $unpacked_atomic_array
* @param Atomic\TKeyedArray|Atomic\TArray|Atomic\TList|Atomic\TClassStringMap $unpacked_atomic_array
*/
private static function coerceValueAfterGatekeeperArgument(
StatementsAnalyzer $statements_analyzer,
@ -1372,9 +1367,9 @@ class ArgumentAnalyzer
$input_type = clone $input_type;
foreach ($param_type->getAtomicTypes() as $param_atomic_type) {
if ($param_atomic_type instanceof Type\Atomic\TGenericObject) {
if ($param_atomic_type instanceof Atomic\TGenericObject) {
foreach ($input_type->getAtomicTypes() as $input_atomic_type) {
if ($input_atomic_type instanceof Type\Atomic\TGenericObject
if ($input_atomic_type instanceof Atomic\TGenericObject
&& $input_atomic_type->value === $param_atomic_type->value
) {
foreach ($input_atomic_type->type_params as $i => $type_param) {
@ -1445,17 +1440,17 @@ class ArgumentAnalyzer
}
if ($unpack) {
if ($unpacked_atomic_array instanceof Type\Atomic\TList) {
if ($unpacked_atomic_array instanceof Atomic\TList) {
$unpacked_atomic_array = clone $unpacked_atomic_array;
$unpacked_atomic_array->type_param = $input_type;
$context->vars_in_scope[$var_id] = new Type\Union([$unpacked_atomic_array]);
} elseif ($unpacked_atomic_array instanceof Type\Atomic\TArray) {
} elseif ($unpacked_atomic_array instanceof Atomic\TArray) {
$unpacked_atomic_array = clone $unpacked_atomic_array;
$unpacked_atomic_array->type_params[1] = $input_type;
$context->vars_in_scope[$var_id] = new Type\Union([$unpacked_atomic_array]);
} elseif ($unpacked_atomic_array instanceof Type\Atomic\TKeyedArray
} elseif ($unpacked_atomic_array instanceof Atomic\TKeyedArray
&& $unpacked_atomic_array->is_list
) {
$unpacked_atomic_array = $unpacked_atomic_array->getList();
@ -1464,7 +1459,7 @@ class ArgumentAnalyzer
$context->vars_in_scope[$var_id] = new Type\Union([$unpacked_atomic_array]);
} else {
$context->vars_in_scope[$var_id] = new Type\Union([
new TArray([
new Atomic\TArray([
Type::getInt(),
$input_type
]),

View File

@ -470,7 +470,7 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
foreach ($intersection_types as $intersection_type) {
$intersection_result = clone $result;
/** @var ?Type\Union */
/** @var ?Type\Union $intersection_result->return_type */
$intersection_result->return_type = null;
self::analyze(

View File

@ -467,8 +467,7 @@ class CallAnalyzer
}
/**
* @param PhpParser\Node\Scalar\String_|PhpParser\Node\Expr\Array_|PhpParser\Node\Expr\BinaryOp\Concat
* $callable_arg
* @param PhpParser\Node\Scalar\String_|PhpParser\Node\Expr\Array_|PhpParser\Node\Expr\BinaryOp\Concat $callable_arg
*
* @return list<non-empty-string>
*

View File

@ -678,10 +678,6 @@ class Scanner
return false;
}
if (isset($this->existing_classlikes_lc[$fq_class_name_lc])) {
throw new \InvalidArgumentException('Why are you asking about a builtin class?');
}
$composer_file_path = $this->config->getComposerFilePathForClassLike($fq_class_name);
if ($composer_file_path && file_exists($composer_file_path)) {

View File

@ -52,7 +52,6 @@ class AstDiffer
$body_change = false;
while ($x < $n && $y < $m && ($is_equal)($a[$x], $b[$y], $a_code, $b_code, $body_change)) {
/** @var bool */
$bc[$x] = $body_change;
++$x;
++$y;

View File

@ -17,5 +17,7 @@ class NodeCounterVisitor extends PhpParser\NodeVisitorAbstract
public function enterNode(PhpParser\Node $node)
{
$this->count++;
return null;
}
}

View File

@ -69,5 +69,7 @@ class OffsetShifterVisitor extends PhpParser\NodeVisitorAbstract
$attrs['endFilePos'] + $this->file_offset + ($this->extra_offsets[$attrs['endFilePos']] ?? 0)
);
$node->setAttribute('startLine', $attrs['startLine'] + $this->line_offset);
return null;
}
}

View File

@ -636,8 +636,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements FileSour
return $this->aliases;
}
public function afterTraverse(array $nodes): void
public function afterTraverse(array $nodes)
{
$this->file_storage->type_aliases = $this->type_aliases;
return null;
}
}

View File

@ -9,6 +9,7 @@ use PhpParser\NameContext;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\NullableType;
use PhpParser\Node\Stmt;
use PhpParser\NodeVisitorAbstract;
@ -167,16 +168,14 @@ class SimpleNameResolver extends NodeVisitorAbstract
}
/**
* @param PhpParser\Node|string|null $node
*
* @return null|PhpParser\Node\Identifier|PhpParser\Node\Name|PhpParser\Node\NullableType
* @psalm-suppress InvalidReturnType
* @psalm-suppress InvalidReturnStatement
* @template T of Node|null
* @param T $node
* @return ($node is NullableType ? NullableType : ($node is Name ? Name : T))
* @psalm-suppress LessSpecificReturnType
*/
private function resolveType($node): ?Node
private function resolveType(?Node $node): ?Node
{
if ($node instanceof Node\NullableType) {
/** @psalm-suppress PossiblyInvalidPropertyAssignmentValue */
if ($node instanceof NullableType) {
$node->type = $this->resolveType($node->type);
return $node;

View File

@ -18,7 +18,7 @@ class TypeMappingVisitor extends NodeVisitorAbstract
$this->real_type_provider = $real_type_provider;
}
public function enterNode(Node $node): void
public function enterNode(Node $node)
{
$origNode = $node;
@ -29,5 +29,7 @@ class TypeMappingVisitor extends NodeVisitorAbstract
/** @psalm-suppress ArgumentTypeCoercion */
$this->real_type_provider->setType($origNode, clone $node_type);
}
return null;
}
}

View File

@ -25,7 +25,7 @@ class ComposerLock
/**
* @param mixed $package
*
* @psalm-assert-if-true array $package
* @psalm-assert-if-true array{name: string, extra: array{psalm: array{pluginClass: string}}} $package
*
* @psalm-pure
*/
@ -78,7 +78,6 @@ class ComposerLock
/** @psalm-suppress MixedAssignment */
foreach ($packages as $package) {
if ($this->isPlugin($package)) {
/** @var array{name:string,extra:array{psalm:array{pluginClass:string}}} */
$ret[] = $package;
}
}

View File

@ -63,7 +63,7 @@ class FakeFileProvider extends FileProvider
public function registerFile(string $file_path, string $file_contents): void
{
$this->fake_files[$file_path] = $file_contents;
$this->fake_file_times[$file_path] = microtime(true);
$this->fake_file_times[$file_path] = (int)microtime(true);
}
/**

View File

@ -3,26 +3,24 @@
namespace Psalm\Internal\Provider;
use PhpParser;
use PhpParser\Node;
use Psalm\Type\Union;
use SplObjectStorage;
class NodeDataProvider implements \Psalm\NodeTypeProvider
{
/** @var SplObjectStorage<PhpParser\Node, Union> */
/** @var SplObjectStorage<Node, Union> */
private $node_types;
/**
* @var SplObjectStorage<
* PhpParser\Node,
* list<non-empty-array<string, non-empty-list<non-empty-list<string>>>>|null
* >
* @var SplObjectStorage<Node,list<non-empty-array<string, non-empty-list<non-empty-list<string>>>>|null>
*/
private $node_assertions;
/** @var SplObjectStorage<PhpParser\Node, array<int, \Psalm\Storage\Assertion>> */
/** @var SplObjectStorage<Node, array<int, \Psalm\Storage\Assertion>> */
private $node_if_true_assertions;
/** @var SplObjectStorage<PhpParser\Node, array<int, \Psalm\Storage\Assertion>> */
/** @var SplObjectStorage<Node, array<int, \Psalm\Storage\Assertion>> */
private $node_if_false_assertions;
/** @var bool */
@ -37,7 +35,7 @@ class NodeDataProvider implements \Psalm\NodeTypeProvider
}
/**
* @param PhpParser\Node\Expr|PhpParser\Node\Name|PhpParser\Node\Stmt\Return_ $node
* @param Node\Expr|Node\Name|Node\Stmt\Return_ $node
*/
public function setType(PhpParser\NodeAbstract $node, Union $type) : void
{
@ -45,7 +43,7 @@ class NodeDataProvider implements \Psalm\NodeTypeProvider
}
/**
* @param PhpParser\Node\Expr|PhpParser\Node\Name|PhpParser\Node\Stmt\Return_ $node
* @param Node\Expr|Node\Name|Node\Stmt\Return_ $node
*/
public function getType(PhpParser\NodeAbstract $node) : ?Union
{
@ -55,7 +53,7 @@ class NodeDataProvider implements \Psalm\NodeTypeProvider
/**
* @param list<non-empty-array<string, non-empty-list<non-empty-list<string>>>>|null $assertions
*/
public function setAssertions(PhpParser\Node\Expr $node, ?array $assertions) : void
public function setAssertions(Node\Expr $node, ?array $assertions) : void
{
if (!$this->cache_assertions) {
return;
@ -67,7 +65,7 @@ class NodeDataProvider implements \Psalm\NodeTypeProvider
/**
* @return list<non-empty-array<string, non-empty-list<non-empty-list<string>>>>|null
*/
public function getAssertions(PhpParser\Node\Expr $node) : ?array
public function getAssertions(Node\Expr $node) : ?array
{
if (!$this->cache_assertions) {
return null;
@ -77,61 +75,49 @@ class NodeDataProvider implements \Psalm\NodeTypeProvider
}
/**
* @param PhpParser\Node\Expr\FuncCall
* |PhpParser\Node\Expr\MethodCall
* |PhpParser\Node\Expr\StaticCall
* |PhpParser\Node\Expr\New_ $node
* @param Node\Expr\FuncCall|Node\Expr\MethodCall|Node\Expr\StaticCall|Node\Expr\New_ $node
* @param array<int, \Psalm\Storage\Assertion> $assertions
*/
public function setIfTrueAssertions(PhpParser\Node\Expr $node, array $assertions) : void
public function setIfTrueAssertions(Node\Expr $node, array $assertions) : void
{
$this->node_if_true_assertions[$node] = $assertions;
}
/**
* @param PhpParser\Node\Expr\FuncCall
* |PhpParser\Node\Expr\MethodCall
* |PhpParser\Node\Expr\StaticCall
* |PhpParser\Node\Expr\New_ $node
* @param Node\Expr\FuncCall|Node\Expr\MethodCall|Node\Expr\StaticCall|Node\Expr\New_ $node
* @return array<int, \Psalm\Storage\Assertion>|null
*/
public function getIfTrueAssertions(PhpParser\Node\Expr $node) : ?array
public function getIfTrueAssertions(Node\Expr $node) : ?array
{
return $this->node_if_true_assertions[$node] ?? null;
}
/**
* @param PhpParser\Node\Expr\FuncCall
* |PhpParser\Node\Expr\MethodCall
* |PhpParser\Node\Expr\StaticCall
* |PhpParser\Node\Expr\New_ $node
* @param Node\Expr\FuncCall|Node\Expr\MethodCall|Node\Expr\StaticCall|Node\Expr\New_ $node
* @param array<int, \Psalm\Storage\Assertion> $assertions
*/
public function setIfFalseAssertions(PhpParser\Node\Expr $node, array $assertions) : void
public function setIfFalseAssertions(Node\Expr $node, array $assertions) : void
{
$this->node_if_false_assertions[$node] = $assertions;
}
/**
* @param PhpParser\Node\Expr\FuncCall
* |PhpParser\Node\Expr\MethodCall
* |PhpParser\Node\Expr\StaticCall
* |PhpParser\Node\Expr\New_ $node
* @param Node\Expr\FuncCall|Node\Expr\MethodCall|Node\Expr\StaticCall|Node\Expr\New_ $node
* @return array<int, \Psalm\Storage\Assertion>|null
*/
public function getIfFalseAssertions(PhpParser\Node\Expr $node) : ?array
public function getIfFalseAssertions(Node\Expr $node) : ?array
{
return $this->node_if_false_assertions[$node] ?? null;
}
public function isPureCompatible(PhpParser\Node\Expr $node) : bool
public function isPureCompatible(Node\Expr $node) : bool
{
$node_type = $this->getType($node);
return ($node_type && $node_type->reference_free) || isset($node->pure);
}
public function clearNodeOfTypeAndAssertions(PhpParser\Node\Expr $node) : void
public function clearNodeOfTypeAndAssertions(Node\Expr $node) : void
{
unset($this->node_types[$node], $this->node_assertions[$node]);
}

View File

@ -15,9 +15,6 @@ class ExplodeReturnTypeProvider implements \Psalm\Plugin\EventHandler\FunctionRe
return ['explode'];
}
/**
* @param list<PhpParser\Node\Arg> $call_args
*/
public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $event) : Type\Union
{
$statements_source = $event->getStatementsSource();

View File

@ -26,6 +26,6 @@ class CaseScope
public function __destruct()
{
$this->parent_context = null;
unset($this->parent_context);
}
}

View File

@ -8,8 +8,10 @@ use Psalm\Context;
*/
class IfConditionalScope
{
/** @var Context */
public $if_context;
/** @var Context */
public $post_if_context;
/**

View File

@ -67,7 +67,7 @@ class LoopScope
public function __destruct()
{
$this->loop_context = null;
$this->loop_parent_context = null;
unset($this->loop_context);
unset($this->loop_parent_context);
}
}

View File

@ -1455,7 +1455,7 @@ class TypeCombiner
if (is_int($property_name)) {
$objectlike_keys[$property_name] = new TLiteralInt($property_name);
} elseif (isset($type->class_strings[$property_name])) {
} elseif ($type instanceof TKeyedArray && isset($type->class_strings[$property_name])) {
$objectlike_keys[$property_name] = new TLiteralClassString($property_name);
} else {
$objectlike_keys[$property_name] = new TLiteralString($property_name);

View File

@ -9,7 +9,7 @@ interface RegistrationInterface
public function addStubFile(string $file_name): void;
/**
* @param string class-string $handler
* @param class-string $handler
*/
public function registerHooksFromClass(string $handler): void;

View File

@ -32,8 +32,6 @@ class Shepherd implements \Psalm\Plugin\EventHandler\AfterAnalysisInterface
{
/**
* Called after analysis is complete
*
* @param array<string, list<IssueData>> $issues
*/
public static function afterAnalysis(
AfterAnalysisEvent $event

View File

@ -11,9 +11,6 @@ class TEnumCase extends TNamedObject
*/
public $case_name;
/**
* @param string $value the name of the object
*/
public function __construct(string $fq_enum_name, string $case_name)
{
parent::__construct($fq_enum_name, false);