From 4a38ab165fc83bd69e6a99839a9e70a819aeb901 Mon Sep 17 00:00:00 2001 From: Matthew Brown Date: Sat, 31 Aug 2019 10:02:11 -0400 Subject: [PATCH] Fix erroneous marking of external-mutation-free method as unused --- .../Expression/Call/MethodCallAnalyzer.php | 3 ++- .../Expression/Call/NewAnalyzer.php | 2 ++ .../Visitor/CheckTrivialExprVisitor.php | 2 +- tests/UnusedCodeTest.php | 22 +++++++++++++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php index eaa5f7a3d..b9611b18f 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php @@ -1250,7 +1250,8 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\ // fall through } } elseif (($method_storage->mutation_free - || $method_pure_compatible) + || ($method_storage->external_mutation_free + && (isset($stmt->var->external_mutation_free) || isset($stmt->var->pure)))) && $codebase->find_unused_variables && !$context->inside_conditional && !$context->inside_unset diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php index c0aab8d45..ad742f686 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php @@ -475,6 +475,8 @@ class NewAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\CallAna } if ($storage->external_mutation_free) { + /** @psalm-suppress UndefinedPropertyAssignment */ + $stmt->external_mutation_free = true; $stmt->inferredType->external_mutation_free = true; } } diff --git a/src/Psalm/Internal/Visitor/CheckTrivialExprVisitor.php b/src/Psalm/Internal/Visitor/CheckTrivialExprVisitor.php index e009ebff2..c9ce2fc63 100644 --- a/src/Psalm/Internal/Visitor/CheckTrivialExprVisitor.php +++ b/src/Psalm/Internal/Visitor/CheckTrivialExprVisitor.php @@ -46,7 +46,7 @@ class CheckTrivialExprVisitor extends PhpParser\NodeVisitorAbstract implements P return false; } - if ($node instanceof PhpParser\Node\Expr\New_ && !empty($node->inferredType->external_mutation_free)) { + if ($node instanceof PhpParser\Node\Expr\New_ && isset($node->external_mutation_free)) { return false; } diff --git a/tests/UnusedCodeTest.php b/tests/UnusedCodeTest.php index 7e89b6d88..9b787cf06 100644 --- a/tests/UnusedCodeTest.php +++ b/tests/UnusedCodeTest.php @@ -584,6 +584,28 @@ class UnusedCodeTest extends TestCase return $arr; }' ], + 'pureFunctionUsesMethodBeforeReturning' => [ + 'count = $count; + } + + public function increment() : void { + $this->count++; + } + } + + /** @psalm-pure */ + function makesACounter(int $i) : Counter { + $c = new Counter($i); + $c->increment(); + return $c; + }', + ], ]; }