Skip to content

Commit

Permalink
flag impure calls made through __callstatic
Browse files Browse the repository at this point in the history
  • Loading branch information
orklah committed Oct 24, 2021
1 parent 307635f commit a0681a4
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\Internal\MethodIdentifier;
use Psalm\Issue\DeprecatedClass;
use Psalm\Issue\ImpureMethodCall;
use Psalm\Issue\InternalClass;
use Psalm\Issue\InvalidStringClass;
use Psalm\Issue\MixedMethodCall;
Expand Down Expand Up @@ -514,6 +515,40 @@ private static function handleNamedCall(
return false;
}

if (!$context->inside_throw) {
if ($context->pure && !$pseudo_method_storage->pure) {
if (IssueBuffer::accepts(
new ImpureMethodCall(
'Cannot call an impure method from a pure context',
new CodeLocation($statements_analyzer, $stmt_name)
),
$statements_analyzer->getSuppressedIssues()
)) {
// fall through
}
} elseif ($context->mutation_free && !$pseudo_method_storage->mutation_free) {
if (IssueBuffer::accepts(
new ImpureMethodCall(
'Cannot call a possibly-mutating method from a mutation-free context',
new CodeLocation($statements_analyzer, $stmt_name)
),
$statements_analyzer->getSuppressedIssues()
)) {
// fall through
}
} elseif ($statements_analyzer->getSource()
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer
&& $statements_analyzer->getSource()->track_mutations
&& !$pseudo_method_storage->pure
) {
if (!$pseudo_method_storage->mutation_free) {
$statements_analyzer->getSource()->inferred_has_mutation = true;
}

$statements_analyzer->getSource()->inferred_impure = true;
}
}

if ($pseudo_method_storage->return_type) {
return true;
}
Expand Down
22 changes: 22 additions & 0 deletions tests/PureAnnotationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,28 @@ function foo(iterable $pieces): string
}',
'error_message' => 'ImpureMethodCall',
],
'impureThroughCallStatic' => [
'<?php
/**
* @method static void test()
*/
final class Impure
{
public static function __callStatic(string $name, array $arguments)
{
}
}
/**
* @psalm-pure
*/
function testImpure(): void
{
Impure::test();
}
',
'error_message' => 'ImpureMethodCall',
],
];
}
}

0 comments on commit a0681a4

Please sign in to comment.