1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00

Add more mixed origin information

This commit is contained in:
Matt Brown 2021-03-20 21:45:38 -04:00
parent 7f8d522912
commit 44c6d3035b
6 changed files with 126 additions and 10 deletions

View File

@ -359,14 +359,16 @@ class AssignmentAnalyzer
? 'Unable to determine the type that ' . $var_id . ' is being assigned to'
: 'Unable to determine the type of this assignment';
if ($origin_location && $origin_location->getLineNumber() === $assign_var->getLine()) {
$issue_location = new CodeLocation($statements_analyzer->getSource(), $assign_var);
if ($origin_location && $origin_location->getHash() === $issue_location->getHash()) {
$origin_location = null;
}
if (IssueBuffer::accepts(
new MixedAssignment(
$message,
new CodeLocation($statements_analyzer->getSource(), $assign_var),
$issue_location,
$origin_location
),
$statements_analyzer->getSuppressedIssues()

View File

@ -14,6 +14,7 @@ use Psalm\Internal\Type\Comparator\CallableTypeComparator;
use Psalm\Internal\Type\Comparator\UnionTypeComparator;
use Psalm\Internal\DataFlow\DataFlowNode;
use Psalm\Internal\Codebase\TaintFlowGraph;
use Psalm\Internal\Codebase\VariableUseGraph;
use Psalm\Internal\MethodIdentifier;
use Psalm\Internal\Scanner\UnresolvedConstantComponent;
use Psalm\Internal\Type\TemplateBound;
@ -611,13 +612,31 @@ class ArgumentAnalyzer
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
}
$origin_locations = [];
if ($statements_analyzer->data_flow_graph instanceof VariableUseGraph) {
foreach ($input_type->parent_nodes as $parent_node) {
$origin_locations = array_merge(
$origin_locations,
$statements_analyzer->data_flow_graph->getOriginLocations($parent_node)
);
}
}
$origin_location = count($origin_locations) === 1 ? reset($origin_locations) : null;
if ($origin_location && $origin_location->getHash() === $arg_location->getHash()) {
$origin_location = null;
}
if (IssueBuffer::accepts(
new MixedArgument(
'Argument ' . ($argument_offset + 1) . $method_identifier
. ' cannot be ' . $input_type->getId() . ', expecting ' .
$param_type,
$arg_location,
$cased_method_id
$cased_method_id,
$origin_location
),
$statements_analyzer->getSuppressedIssues()
)) {

View File

@ -11,6 +11,7 @@ use Psalm\Internal\Analyzer\Statements\Expression\Call\ClassTemplateParamCollect
use Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\Internal\Codebase\InternalCallMapHandler;
use Psalm\Internal\Codebase\VariableUseGraph;
use Psalm\Codebase;
use Psalm\CodeLocation;
use Psalm\Context;
@ -44,6 +45,7 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
PhpParser\Node\Expr\MethodCall $stmt,
Codebase $codebase,
Context $context,
Type\Union $lhs_type,
Type\Atomic $lhs_type_part,
?Type\Atomic $static_type,
bool $is_intersection,
@ -80,6 +82,7 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
$statements_analyzer,
$codebase,
$stmt,
$lhs_type,
$lhs_type_part,
$lhs_var_id,
$context,
@ -269,6 +272,7 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
$stmt,
$codebase,
$context,
$lhs_type,
$lhs_type_part,
$lhs_var_id,
$result,
@ -451,6 +455,7 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
PhpParser\Node\Expr\MethodCall $stmt,
Codebase $codebase,
Context $context,
Type\Union $lhs_type,
Type\Atomic $lhs_type_part,
?string $lhs_var_id,
AtomicMethodCallAnalysisResult $result,
@ -470,6 +475,7 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
$stmt,
$codebase,
$context,
$lhs_type,
$intersection_type,
$lhs_type_part,
true,
@ -544,6 +550,7 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
StatementsAnalyzer $statements_analyzer,
Codebase $codebase,
PhpParser\Node\Expr\MethodCall $stmt,
Type\Union $lhs_type,
Type\Atomic $lhs_type_part,
?string $lhs_var_id,
Context $context,
@ -600,10 +607,30 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
}
}
$origin_locations = [];
if ($statements_analyzer->data_flow_graph instanceof VariableUseGraph) {
foreach ($lhs_type->parent_nodes as $parent_node) {
$origin_locations = array_merge(
$origin_locations,
$statements_analyzer->data_flow_graph->getOriginLocations($parent_node)
);
}
}
$origin_location = count($origin_locations) === 1 ? reset($origin_locations) : null;
$name_code_location = new CodeLocation($statements_analyzer, $stmt->name);
if ($origin_location && $origin_location->getHash() === $name_code_location->getHash()) {
$origin_location = null;
}
if (IssueBuffer::accepts(
new MixedMethodCall(
$message,
new CodeLocation($statements_analyzer, $stmt->name)
$name_code_location,
$origin_location
),
$statements_analyzer->getSuppressedIssues()
)) {

View File

@ -185,6 +185,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
$stmt,
$codebase,
$context,
$class_type,
$lhs_type_part,
$lhs_type_part instanceof Type\Atomic\TNamedObject
|| $lhs_type_part instanceof Type\Atomic\TTemplateParam

View File

@ -16,6 +16,7 @@ use Psalm\Context;
use Psalm\Exception\DocblockParseException;
use Psalm\Internal\DataFlow\DataFlowNode;
use Psalm\Internal\Codebase\TaintFlowGraph;
use Psalm\Internal\Codebase\VariableUseGraph;
use Psalm\Internal\Type\TemplateResult;
use Psalm\Internal\Type\TemplateInferredTypeReplacer;
use Psalm\Issue\FalsableReturnStatement;
@ -303,10 +304,30 @@ class ReturnAnalyzer
}
if ($stmt_type->isMixed()) {
$origin_locations = [];
if ($statements_analyzer->data_flow_graph instanceof VariableUseGraph) {
foreach ($stmt_type->parent_nodes as $parent_node) {
$origin_locations = array_merge(
$origin_locations,
$statements_analyzer->data_flow_graph->getOriginLocations($parent_node)
);
}
}
$origin_location = count($origin_locations) === 1 ? reset($origin_locations) : null;
$return_location = new CodeLocation($source, $stmt->expr);
if ($origin_location && $origin_location->getHash() === $return_location->getHash()) {
$origin_location = null;
}
if (IssueBuffer::accepts(
new MixedReturnStatement(
'Could not infer a return type',
new CodeLocation($source, $stmt->expr)
$return_location,
$origin_location
),
$statements_analyzer->getSuppressedIssues()
)) {

View File

@ -3176,7 +3176,7 @@ class UnusedVariableTest extends TestCase
function takesArray(array $arr) : void {
foreach ($arr as $a) {}
}',
'error_message' => 'MixedAssignment - src' . DIRECTORY_SEPARATOR . 'somefile.php:3:42 - Unable to determine the type that $a is being assigned to, derived from expression at src' . DIRECTORY_SEPARATOR . 'somefile.php:2:47'
'error_message' => 'MixedAssignment - src' . DIRECTORY_SEPARATOR . 'somefile.php:3:42 - Unable to determine the type that $a is being assigned to. Consider improving the type at src' . DIRECTORY_SEPARATOR . 'somefile.php:2:47'
],
'warnAboutOriginalBadFunctionCall' => [
'<?php
@ -3189,7 +3189,7 @@ class UnusedVariableTest extends TestCase
foreach ($arr as $a) {
echo $a;
}',
'error_message' => 'MixedAssignment - src' . DIRECTORY_SEPARATOR . 'somefile.php:8:38 - Unable to determine the type that $a is being assigned to, derived from expression at src' . DIRECTORY_SEPARATOR . 'somefile.php:2:44'
'error_message' => 'MixedAssignment - src' . DIRECTORY_SEPARATOR . 'somefile.php:8:38 - Unable to determine the type that $a is being assigned to. Consider improving the type at src' . DIRECTORY_SEPARATOR . 'somefile.php:2:44'
],
'warnAboutOriginalBadStaticCall' => [
'<?php
@ -3204,7 +3204,7 @@ class UnusedVariableTest extends TestCase
foreach ($arr as $a) {
echo $a;
}',
'error_message' => 'MixedAssignment - src' . DIRECTORY_SEPARATOR . 'somefile.php:10:38 - Unable to determine the type that $a is being assigned to, derived from expression at src' . DIRECTORY_SEPARATOR . 'somefile.php:3:62'
'error_message' => 'MixedAssignment - src' . DIRECTORY_SEPARATOR . 'somefile.php:10:38 - Unable to determine the type that $a is being assigned to. Consider improving the type at src' . DIRECTORY_SEPARATOR . 'somefile.php:3:62'
],
'warnAboutOriginalBadInstanceCall' => [
'<?php
@ -3219,7 +3219,7 @@ class UnusedVariableTest extends TestCase
foreach ($arr as $a) {
echo $a;
}',
'error_message' => 'MixedAssignment - src' . DIRECTORY_SEPARATOR . 'somefile.php:10:38 - Unable to determine the type that $a is being assigned to, derived from expression at src' . DIRECTORY_SEPARATOR . 'somefile.php:3:55'
'error_message' => 'MixedAssignment - src' . DIRECTORY_SEPARATOR . 'somefile.php:10:38 - Unable to determine the type that $a is being assigned to. Consider improving the type at src' . DIRECTORY_SEPARATOR . 'somefile.php:3:55'
],
'warnAboutDocblockReturnType' => [
'<?php
@ -3235,7 +3235,53 @@ class UnusedVariableTest extends TestCase
echo $a;
}
}',
'error_message' => 'MixedAssignment - src' . DIRECTORY_SEPARATOR . 'somefile.php:10:47 - Unable to determine the type that $a is being assigned to, derived from expression at src' . DIRECTORY_SEPARATOR . 'somefile.php:2:33'
'error_message' => 'MixedAssignment - src' . DIRECTORY_SEPARATOR . 'somefile.php:10:47 - Unable to determine the type that $a is being assigned to. Consider improving the type at src' . DIRECTORY_SEPARATOR . 'somefile.php:2:33'
],
'warnAboutMixedArgument' => [
'<?php
function makeArray() : array {
return ["hello"];
}
$arr = makeArray();
/** @psalm-suppress MixedAssignment */
foreach ($arr as $a) {
echo $a;
}',
'error_message' => 'MixedArgument - src' . DIRECTORY_SEPARATOR . 'somefile.php:10:30 - Argument 1 of echo cannot be mixed, expecting string. Consider improving the type at src' . DIRECTORY_SEPARATOR . 'somefile.php:2:44'
],
'warnAboutMixedMethodCall' => [
'<?php
function makeArray() : array {
return ["hello"];
}
$arr = makeArray();
/** @psalm-suppress MixedAssignment */
foreach ($arr as $a) {
$a->foo();
}',
'error_message' => 'MixedMethodCall - src' . DIRECTORY_SEPARATOR . 'somefile.php:10:29 - Cannot determine the type of $a when calling method foo. Consider improving the type at src' . DIRECTORY_SEPARATOR . 'somefile.php:2:44'
],
'warnAboutMixedReturnStatement' => [
'<?php
function makeArray() : array {
return ["hello"];
}
function foo() : string {
$arr = makeArray();
/** @psalm-suppress MixedAssignment */
foreach ($arr as $a) {
return $a;
}
return "";
}',
'error_message' => 'MixedReturnStatement - src' . DIRECTORY_SEPARATOR . 'somefile.php:11:36 - Could not infer a return type. Consider improving the type at src' . DIRECTORY_SEPARATOR . 'somefile.php:2:44'
],
];
}