mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
commit
afbda6d0f6
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -662,7 +662,6 @@ class FileAnalyzer extends SourceAnalyzer
|
||||
|
||||
public function clearSourceBeforeDestruction() : void
|
||||
{
|
||||
/** @psalm-suppress PossiblyNullPropertyAssignmentValue */
|
||||
$this->source = null;
|
||||
unset($this->source);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ abstract class SourceAnalyzer implements StatementsSource
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->source = null;
|
||||
unset($this->source);
|
||||
}
|
||||
|
||||
public function getAliases(): Aliases
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 = [];
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
]),
|
||||
|
@ -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(
|
||||
|
@ -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>
|
||||
*
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -17,5 +17,7 @@ class NodeCounterVisitor extends PhpParser\NodeVisitorAbstract
|
||||
public function enterNode(PhpParser\Node $node)
|
||||
{
|
||||
$this->count++;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -26,6 +26,6 @@ class CaseScope
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->parent_context = null;
|
||||
unset($this->parent_context);
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,10 @@ use Psalm\Context;
|
||||
*/
|
||||
class IfConditionalScope
|
||||
{
|
||||
/** @var Context */
|
||||
public $if_context;
|
||||
|
||||
/** @var Context */
|
||||
public $post_if_context;
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user