1
0
mirror of https://github.com/danog/psalm.git synced 2024-12-02 09:37:59 +01:00

Merge pull request #10756 from edsrzf/array-isset

This commit is contained in:
Bruce Weirdan 2024-03-20 02:27:19 +01:00 committed by GitHub
commit 70530d6a0c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 60 additions and 32 deletions

View File

@ -1,10 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="5.x-dev@ba4e312594006059b0d9afb0c5ebeea649a59112"> <files psalm-version="5.x-dev@a46a07c5ca8bd7b54d1ca814c1f5b5ed38a0ba90">
<file src="vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php">
<PossiblyUndefinedStringArrayOffset>
<code><![CDATA[$subNodes['expr']]]></code>
</PossiblyUndefinedStringArrayOffset>
</file>
<file src="examples/TemplateChecker.php"> <file src="examples/TemplateChecker.php">
<PossiblyUndefinedIntArrayOffset> <PossiblyUndefinedIntArrayOffset>
<code><![CDATA[$comment_block->tags['variablesfrom'][0]]]></code> <code><![CDATA[$comment_block->tags['variablesfrom'][0]]]></code>
@ -75,7 +70,6 @@
<code><![CDATA[!$config_path]]></code> <code><![CDATA[!$config_path]]></code>
<code><![CDATA[!$file_path]]></code> <code><![CDATA[!$file_path]]></code>
<code><![CDATA[!strpos($issue_type, 'Reference')]]></code> <code><![CDATA[!strpos($issue_type, 'Reference')]]></code>
<code><![CDATA[$cwd]]></code>
<code><![CDATA[$dir]]></code> <code><![CDATA[$dir]]></code>
<code><![CDATA[$e->function_id]]></code> <code><![CDATA[$e->function_id]]></code>
<code><![CDATA[$igbinary_version = phpversion('igbinary')]]></code> <code><![CDATA[$igbinary_version = phpversion('igbinary')]]></code>
@ -716,6 +710,7 @@
<code><![CDATA[$overridden_template_types]]></code> <code><![CDATA[$overridden_template_types]]></code>
<code><![CDATA[$static_class_storage->template_extended_params]]></code> <code><![CDATA[$static_class_storage->template_extended_params]]></code>
<code><![CDATA[$static_class_storage->template_types]]></code> <code><![CDATA[$static_class_storage->template_types]]></code>
<code><![CDATA[empty($non_trait_class_storage->overridden_method_ids[$method_name])]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
<file src="src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php"> <file src="src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php">
@ -865,8 +860,6 @@
<code><![CDATA[!$context->self]]></code> <code><![CDATA[!$context->self]]></code>
<code><![CDATA[!$fq_class_name]]></code> <code><![CDATA[!$fq_class_name]]></code>
<code><![CDATA[$class_storage->mixin_declaring_fqcln]]></code> <code><![CDATA[$class_storage->mixin_declaring_fqcln]]></code>
<code><![CDATA[$class_storage->parent_class]]></code>
<code><![CDATA[$class_storage->parent_class]]></code>
<code><![CDATA[$context->calling_method_id]]></code> <code><![CDATA[$context->calling_method_id]]></code>
<code><![CDATA[$context->calling_method_id]]></code> <code><![CDATA[$context->calling_method_id]]></code>
<code><![CDATA[$context->self]]></code> <code><![CDATA[$context->self]]></code>
@ -945,8 +938,6 @@
<code><![CDATA[$extended_var_id]]></code> <code><![CDATA[$extended_var_id]]></code>
<code><![CDATA[$keyed_array_var_id]]></code> <code><![CDATA[$keyed_array_var_id]]></code>
<code><![CDATA[$keyed_array_var_id]]></code> <code><![CDATA[$keyed_array_var_id]]></code>
<code><![CDATA[$keyed_array_var_id]]></code>
<code><![CDATA[$keyed_array_var_id]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
<file src="src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/AtomicPropertyFetchAnalyzer.php"> <file src="src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/AtomicPropertyFetchAnalyzer.php">
@ -1104,7 +1095,6 @@
</file> </file>
<file src="src/Psalm/Internal/Cli/LanguageServer.php"> <file src="src/Psalm/Internal/Cli/LanguageServer.php">
<RiskyTruthyFalsyComparison> <RiskyTruthyFalsyComparison>
<code><![CDATA[!$root_path]]></code>
<code><![CDATA[$options['verbose']]]></code> <code><![CDATA[$options['verbose']]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
@ -1115,9 +1105,6 @@
<RiskyTruthyFalsyComparison> <RiskyTruthyFalsyComparison>
<code><![CDATA[!$config->error_baseline]]></code> <code><![CDATA[!$config->error_baseline]]></code>
<code><![CDATA[!$paths_to_check]]></code> <code><![CDATA[!$paths_to_check]]></code>
<code><![CDATA[!$root_path]]></code>
<code><![CDATA[!file_put_contents($current_dir . 'psalm.xml', $template_contents)]]></code>
<code><![CDATA[!file_put_contents($current_dir . 'psalm.xml', $template_contents)]]></code>
<code><![CDATA[$baseline_file_path]]></code> <code><![CDATA[$baseline_file_path]]></code>
<code><![CDATA[$cache_directory]]></code> <code><![CDATA[$cache_directory]]></code>
<code><![CDATA[$config->threads]]></code> <code><![CDATA[$config->threads]]></code>
@ -1128,7 +1115,6 @@
</file> </file>
<file src="src/Psalm/Internal/Cli/Psalter.php"> <file src="src/Psalm/Internal/Cli/Psalter.php">
<RiskyTruthyFalsyComparison> <RiskyTruthyFalsyComparison>
<code><![CDATA[!$root_path]]></code>
<code><![CDATA[$paths_to_check]]></code> <code><![CDATA[$paths_to_check]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
@ -1140,7 +1126,6 @@
<code><![CDATA[!$last_arg]]></code> <code><![CDATA[!$last_arg]]></code>
<code><![CDATA[!$last_arg]]></code> <code><![CDATA[!$last_arg]]></code>
<code><![CDATA[!$last_arg]]></code> <code><![CDATA[!$last_arg]]></code>
<code><![CDATA[!$root_path]]></code>
<code><![CDATA[strpos($last_arg_part, '::')]]></code> <code><![CDATA[strpos($last_arg_part, '::')]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
@ -1201,11 +1186,7 @@
<code><![CDATA[$file_path]]></code> <code><![CDATA[$file_path]]></code>
<code><![CDATA[$migrated_source_fqcln]]></code> <code><![CDATA[$migrated_source_fqcln]]></code>
<code><![CDATA[$migrated_source_fqcln]]></code> <code><![CDATA[$migrated_source_fqcln]]></code>
</RiskyTruthyFalsyComparison> <code><![CDATA[empty($classlike_storage->overridden_method_ids[$method_name])]]></code>
</file>
<file src="src/Psalm/Internal/Codebase/ConstantTypeResolver.php">
<RiskyTruthyFalsyComparison>
<code><![CDATA[$cond->value]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
<file src="src/Psalm/Internal/Codebase/Functions.php"> <file src="src/Psalm/Internal/Codebase/Functions.php">
@ -1441,7 +1422,6 @@
</file> </file>
<file src="src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeDocblockParser.php"> <file src="src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeDocblockParser.php">
<PossiblyUndefinedIntArrayOffset> <PossiblyUndefinedIntArrayOffset>
<code><![CDATA[$doc_line_parts[1]]]></code>
<code><![CDATA[$matches[0]]]></code> <code><![CDATA[$matches[0]]]></code>
<code><![CDATA[$method_tree->children[0]]]></code> <code><![CDATA[$method_tree->children[0]]]></code>
<code><![CDATA[$method_tree->children[1]]]></code> <code><![CDATA[$method_tree->children[1]]]></code>
@ -1475,6 +1455,9 @@
<code><![CDATA[$var_comment->line_number]]></code> <code><![CDATA[$var_comment->line_number]]></code>
<code><![CDATA[$var_comment->type_end]]></code> <code><![CDATA[$var_comment->type_end]]></code>
<code><![CDATA[$var_comment->type_start]]></code> <code><![CDATA[$var_comment->type_start]]></code>
<code><![CDATA[empty($imported_type_data[0])]]></code>
<code><![CDATA[empty($imported_type_data[2])]]></code>
<code><![CDATA[empty($imported_type_data[4])]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
<file src="src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php"> <file src="src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php">
@ -1498,12 +1481,12 @@
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
<file src="src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockParser.php"> <file src="src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockParser.php">
<PossiblyUndefinedIntArrayOffset>
<code><![CDATA[$since_parts[1]]]></code>
</PossiblyUndefinedIntArrayOffset>
<RedundantCondition> <RedundantCondition>
<code><![CDATA[count($line_parts) > 0]]></code> <code><![CDATA[count($line_parts) > 0]]></code>
</RedundantCondition> </RedundantCondition>
<RiskyTruthyFalsyComparison>
<code><![CDATA[empty($since_match[4])]]></code>
</RiskyTruthyFalsyComparison>
</file> </file>
<file src="src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php"> <file src="src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php">
<PossiblyUndefinedArrayOffset> <PossiblyUndefinedArrayOffset>
@ -1636,6 +1619,13 @@
<file src="src/Psalm/Internal/Provider/FileReferenceProvider.php"> <file src="src/Psalm/Internal/Provider/FileReferenceProvider.php">
<RiskyTruthyFalsyComparison> <RiskyTruthyFalsyComparison>
<code><![CDATA[$this->cache->getFileMapCache()]]></code> <code><![CDATA[$this->cache->getFileMapCache()]]></code>
<code><![CDATA[empty(self::$file_references_to_class_members[$method_id])]]></code>
<code><![CDATA[empty(self::$file_references_to_class_properties[$property_id])]]></code>
<code><![CDATA[empty(self::$file_references_to_method_returns[$method_id])]]></code>
<code><![CDATA[empty(self::$method_param_uses[$method_id][$offset])]]></code>
<code><![CDATA[empty(self::$method_references_to_class_members[$method_id])]]></code>
<code><![CDATA[empty(self::$method_references_to_class_properties[$property_id])]]></code>
<code><![CDATA[empty(self::$method_references_to_method_returns[$method_id])]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
<file src="src/Psalm/Internal/Provider/FileStorageCacheProvider.php"> <file src="src/Psalm/Internal/Provider/FileStorageCacheProvider.php">
@ -1730,6 +1720,7 @@
<file src="src/Psalm/Internal/Scanner/DocblockParser.php"> <file src="src/Psalm/Internal/Scanner/DocblockParser.php">
<RiskyTruthyFalsyComparison> <RiskyTruthyFalsyComparison>
<code><![CDATA[$first_line_padding]]></code> <code><![CDATA[$first_line_padding]]></code>
<code><![CDATA[empty($special[$type])]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
<file src="src/Psalm/Internal/Scanner/PhpStormMetaScanner.php"> <file src="src/Psalm/Internal/Scanner/PhpStormMetaScanner.php">
@ -1884,6 +1875,7 @@
<file src="src/Psalm/Internal/Type/TemplateInferredTypeReplacer.php"> <file src="src/Psalm/Internal/Type/TemplateInferredTypeReplacer.php">
<RiskyTruthyFalsyComparison> <RiskyTruthyFalsyComparison>
<code><![CDATA[$classlike_storage->template_extended_params]]></code> <code><![CDATA[$classlike_storage->template_extended_params]]></code>
<code><![CDATA[empty($inferred_lower_bounds[$atomic_type->offset_param_name])]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
<file src="src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php"> <file src="src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php">
@ -1897,6 +1889,7 @@
<code><![CDATA[empty($class_storage->template_extended_params[$container_class])]]></code> <code><![CDATA[empty($class_storage->template_extended_params[$container_class])]]></code>
<code><![CDATA[empty($classlike_storage->template_extended_params[$base_type->as_type->value])]]></code> <code><![CDATA[empty($classlike_storage->template_extended_params[$base_type->as_type->value])]]></code>
<code><![CDATA[empty($classlike_storage->template_extended_params[$base_type->value])]]></code> <code><![CDATA[empty($classlike_storage->template_extended_params[$base_type->value])]]></code>
<code><![CDATA[empty($template_result->lower_bounds[$atomic_type->offset_param_name])]]></code>
<code><![CDATA[strpos($key, '&')]]></code> <code><![CDATA[strpos($key, '&')]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
@ -1929,9 +1922,6 @@
<code><![CDATA[$combination->strings]]></code> <code><![CDATA[$combination->strings]]></code>
<code><![CDATA[$combination->strings]]></code> <code><![CDATA[$combination->strings]]></code>
<code><![CDATA[$combination->strings]]></code> <code><![CDATA[$combination->strings]]></code>
<code><![CDATA[$combination->value_types['string'] instanceof TNonFalsyString
? $type->value
: $type->value !== '']]></code>
<code><![CDATA[$shared_classlikes]]></code> <code><![CDATA[$shared_classlikes]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
@ -2278,7 +2268,6 @@
<RiskyTruthyFalsyComparison> <RiskyTruthyFalsyComparison>
<code><![CDATA[!strpos($key, '$')]]></code> <code><![CDATA[!strpos($key, '$')]]></code>
<code><![CDATA[!strpos($key, '[')]]></code> <code><![CDATA[!strpos($key, '[')]]></code>
<code><![CDATA[$array_key_offset]]></code>
<code><![CDATA[$failed_reconciliation]]></code> <code><![CDATA[$failed_reconciliation]]></code>
<code><![CDATA[strpos($base_key, '::')]]></code> <code><![CDATA[strpos($base_key, '::')]]></code>
<code><![CDATA[strpos($key, '::')]]></code> <code><![CDATA[strpos($key, '::')]]></code>
@ -2348,6 +2337,11 @@
<code><![CDATA[strpos(static::class, 'Unused')]]></code> <code><![CDATA[strpos(static::class, 'Unused')]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
<file src="tests/Internal/Codebase/InternalCallMapHandlerTest.php">
<RiskyTruthyFalsyComparison>
<code><![CDATA[empty($normalizedEntry['type'])]]></code>
</RiskyTruthyFalsyComparison>
</file>
<file src="tests/TypeParseTest.php"> <file src="tests/TypeParseTest.php">
<RiskyTruthyFalsyComparison> <RiskyTruthyFalsyComparison>
<code><![CDATA[$param_type_1]]></code> <code><![CDATA[$param_type_1]]></code>
@ -2357,4 +2351,9 @@
<code><![CDATA[$return_type]]></code> <code><![CDATA[$return_type]]></code>
</RiskyTruthyFalsyComparison> </RiskyTruthyFalsyComparison>
</file> </file>
<file src="vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php">
<PossiblyUndefinedStringArrayOffset>
<code><![CDATA[$subNodes['expr']]]></code>
</PossiblyUndefinedStringArrayOffset>
</file>
</files> </files>

View File

@ -171,7 +171,7 @@ final class ArrayFetchAnalyzer
$codebase = $statements_analyzer->getCodebase(); $codebase = $statements_analyzer->getCodebase();
if ($keyed_array_var_id if ($keyed_array_var_id !== null
&& $context->hasVariable($keyed_array_var_id) && $context->hasVariable($keyed_array_var_id)
&& !$context->vars_in_scope[$keyed_array_var_id]->possibly_undefined && !$context->vars_in_scope[$keyed_array_var_id]->possibly_undefined
&& $stmt_var_type && $stmt_var_type
@ -250,6 +250,10 @@ final class ArrayFetchAnalyzer
} }
} }
if ($context->inside_isset && !$stmt_type->hasMixed()) {
$stmt_type = Type::combineUnionTypes($stmt_type, Type::getNull());
}
$statements_analyzer->node_data->setType($stmt, $stmt_type); $statements_analyzer->node_data->setType($stmt, $stmt_type);
if ($context->inside_isset if ($context->inside_isset
@ -304,7 +308,7 @@ final class ArrayFetchAnalyzer
} }
} }
if ($keyed_array_var_id if ($keyed_array_var_id !== null
&& $context->hasVariable($keyed_array_var_id) && $context->hasVariable($keyed_array_var_id)
&& (!($stmt_type = $statements_analyzer->node_data->getType($stmt)) || $stmt_type->isVanillaMixed()) && (!($stmt_type = $statements_analyzer->node_data->getType($stmt)) || $stmt_type->isVanillaMixed())
) { ) {

View File

@ -1234,6 +1234,8 @@ class ArrayAssignmentTest extends TestCase
foreach ($arr[0] as $k => $v) {} foreach ($arr[0] as $k => $v) {}
} }
}', }',
'assertions' => [],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
], ],
'nonEmptyAssignmentToListElement' => [ 'nonEmptyAssignmentToListElement' => [
'code' => '<?php 'code' => '<?php

View File

@ -2602,6 +2602,7 @@ class ArrayFunctionCallTest extends TestCase
'assertions' => [ 'assertions' => [
'$line===' => 'array{0: int, ...<array-key, int>}', '$line===' => 'array{0: int, ...<array-key, int>}',
], ],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
], ],
'arrayUnshiftOnEmptyArrayMeansNonEmptyList' => [ 'arrayUnshiftOnEmptyArrayMeansNonEmptyList' => [
'code' => '<?php 'code' => '<?php

View File

@ -231,6 +231,8 @@ class EmptyTest extends TestCase
function foo(array $o) : void { function foo(array $o) : void {
if (empty($o[0]) && empty($o[1])) {} if (empty($o[0]) && empty($o[1])) {}
}', }',
'assertions' => [],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
], ],
'multipleEmptiesInConditionWithMixedOffset' => [ 'multipleEmptiesInConditionWithMixedOffset' => [
'code' => '<?php 'code' => '<?php
@ -315,6 +317,8 @@ class EmptyTest extends TestCase
if (empty($data[Foo::ONE])) {} if (empty($data[Foo::ONE])) {}
} }
}', }',
'assertions' => [],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
], ],
'doubleEmptyCheckTwoArrays' => [ 'doubleEmptyCheckTwoArrays' => [
'code' => '<?php 'code' => '<?php
@ -330,6 +334,8 @@ class EmptyTest extends TestCase
function foo(array $arr) : void { function foo(array $arr) : void {
if (empty($arr["a"]) && empty($arr["b"])) {} if (empty($arr["a"]) && empty($arr["b"])) {}
}', }',
'assertions' => [],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
], ],
'doubleEmptyCheckOnTKeyedArrayVariableOffsets' => [ 'doubleEmptyCheckOnTKeyedArrayVariableOffsets' => [
'code' => '<?php 'code' => '<?php
@ -340,6 +346,8 @@ class EmptyTest extends TestCase
if (empty($arr[$i]) && empty($arr[$j])) {} if (empty($arr[$i]) && empty($arr[$j])) {}
}', }',
'assertions' => [],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
], ],
'checkArrayEmptyUnknownRoot' => [ 'checkArrayEmptyUnknownRoot' => [
'code' => '<?php 'code' => '<?php
@ -626,6 +634,11 @@ class EmptyTest extends TestCase
'$x===' => 'true', '$x===' => 'true',
], ],
], ],
'emptyArrayFetch' => [
'code' => '<?php
/** @var array<true> $a */
if (empty($a["a"])) {}',
],
]; ];
} }
@ -758,6 +771,13 @@ class EmptyTest extends TestCase
}', }',
'error_message' => 'RedundantConditionGivenDocblockType', 'error_message' => 'RedundantConditionGivenDocblockType',
], ],
'redundantEmptyArrayFetch' => [
'code' => '<?php
/** @var array<true> $a */;
assert(isset($a["a"]));
if (empty($a["a"])) {}',
'error_message' => 'DocblockTypeContradiction',
],
]; ];
} }
} }

View File

@ -575,6 +575,8 @@ class RedundantConditionTest extends TestCase
if (empty($a["foo"])) {} if (empty($a["foo"])) {}
} }
}', }',
'assertions' => [],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
], ],
'suppressRedundantConditionAfterAssertNonEmpty' => [ 'suppressRedundantConditionAfterAssertNonEmpty' => [
'code' => '<?php 'code' => '<?php