Skip to content
Permalink
Browse files

Fix #2460 - allow assertions on immutable method calls

  • Loading branch information
muglug committed Dec 12, 2019
1 parent 8f25183 commit f45014d403fc8189f5dec92cf7c4120e93edf3c0
@@ -1064,6 +1064,8 @@ function (PhpParser\Node\Arg $arg) {
$declaring_method_id ?: $method_id
);

$can_memoize = false;

if ($method_name_lc === '__tostring') {
$return_type_candidate = Type::getString();
} else {
@@ -1326,24 +1328,33 @@ function (PhpParser\Node\Arg $arg) {
} elseif (($method_storage->mutation_free
|| ($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
) {
if (!$context->inside_assignment && !$context->inside_call) {
if (IssueBuffer::accepts(
new \Psalm\Issue\UnusedMethodCall(
'The call to ' . $cased_method_id . ' is not used',
new CodeLocation($statements_analyzer, $stmt->name),
$method_id
),
$statements_analyzer->getSuppressedIssues()
)) {
// fall through
if ($method_storage->mutation_free && !$method_storage->mutation_free_inferred) {
if ($context->inside_conditional) {
/** @psalm-suppress UndefinedPropertyAssignment */
$stmt->pure = true;
}

$can_memoize = true;
}

if ($codebase->find_unused_variables && !$context->inside_conditional) {
if (!$context->inside_assignment && !$context->inside_call) {
if (IssueBuffer::accepts(
new \Psalm\Issue\UnusedMethodCall(
'The call to ' . $cased_method_id . ' is not used',
new CodeLocation($statements_analyzer, $stmt->name),
$method_id
),
$statements_analyzer->getSuppressedIssues()
)) {
// fall through
}
} else {
/** @psalm-suppress UndefinedPropertyAssignment */
$stmt->pure = true;
}
} else {
/** @psalm-suppress UndefinedPropertyAssignment */
$stmt->pure = true;
}
}

@@ -1416,7 +1427,7 @@ function (Assertion $assertion) use ($class_template_params) : Assertion {
}

if (!$args && $lhs_var_id) {
if ($config->memoize_method_calls) {
if ($config->memoize_method_calls || $can_memoize) {
$method_var_id = $lhs_var_id . '->' . $method_name_lc . '()';

if (isset($context->vars_in_scope[$method_var_id])) {
@@ -1099,7 +1099,7 @@ public static function getArrayVarId(
) {
$config = \Psalm\Config::getInstance();

if ($config->memoize_method_calls) {
if ($config->memoize_method_calls || isset($stmt->pure)) {
$lhs_var_name = self::getArrayVarId(
$stmt->var,
$this_class_name,
@@ -1851,6 +1851,8 @@ private function registerFunctionLike(PhpParser\Node\FunctionLike $stmt, $fake_m
) {
if ($stmt instanceof PhpParser\Node\Stmt\ClassMethod
&& $storage instanceof MethodStorage
&& $class_storage
&& !$class_storage->mutation_free
&& count($stmt->stmts) === 1
&& !count($stmt->params)
&& $stmt->stmts[0] instanceof PhpParser\Node\Stmt\Return_
@@ -252,6 +252,32 @@ public function withBar(string $bar): self {
}
}',
],
'memoizeImmutableCalls' => [
'<?php
function takesString(string $s) : void {}
/**
* @psalm-immutable
*/
class DTO {
/** @var string|null */
private $error;
public function __construct(?string $error) {
$this->error = $error;
}
public function getError(): ?string {
return $this->error;
}
}
$dto = new DTO("BOOM!");
if ($dto->getError()) {
takesString($dto->getError());
}'
],
];
}

0 comments on commit f45014d

Please sign in to comment.
You can’t perform that action at this time.