Skip to content

Commit

Permalink
Merge pull request #8155 from Nicelocal/prohibition_analyzer_clone
Browse files Browse the repository at this point in the history
Run method call prohibition analyzer when cloning
  • Loading branch information
orklah committed Jun 24, 2022
2 parents f2f211c + 7a5120c commit 8b7bc07
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 4 deletions.
Expand Up @@ -6,6 +6,7 @@
use Psalm\CodeLocation;
use Psalm\Context;
use Psalm\Internal\Analyzer\MethodAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MethodCallProhibitionAnalyzer;
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\Internal\MethodIdentifier;
Expand Down Expand Up @@ -39,6 +40,7 @@ public static function analyze(
return false;
}

$location = new CodeLocation($statements_analyzer->getSource(), $stmt);
$stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr);

if ($stmt_expr_type) {
Expand Down Expand Up @@ -71,7 +73,7 @@ public static function analyze(
$does_method_exist = $codebase_methods->methodExists(
$clone_method_id,
$context->calling_method_id,
new CodeLocation($statements_analyzer->getSource(), $stmt)
$location
);
$is_method_visible = MethodAnalyzer::isMethodVisible(
$clone_method_id,
Expand All @@ -81,6 +83,14 @@ public static function analyze(
if ($does_method_exist && !$is_method_visible) {
$invalid_clones[] = $clone_type_part->getId();
} else {
MethodCallProhibitionAnalyzer::analyze(
$codebase,
$context,
$clone_method_id,
$statements_analyzer->getNamespace(),
$location,
$statements_analyzer->getSuppressedIssues()
);
$possibly_valid = true;
$immutable_cloned = true;
}
Expand Down Expand Up @@ -108,7 +118,7 @@ public static function analyze(
IssueBuffer::maybeAdd(
new MixedClone(
'Cannot clone mixed',
new CodeLocation($statements_analyzer->getSource(), $stmt)
$location
),
$statements_analyzer->getSuppressedIssues()
);
Expand All @@ -119,15 +129,15 @@ public static function analyze(
IssueBuffer::maybeAdd(
new PossiblyInvalidClone(
'Cannot clone ' . $invalid_clones[0],
new CodeLocation($statements_analyzer->getSource(), $stmt)
$location
),
$statements_analyzer->getSuppressedIssues()
);
} else {
IssueBuffer::maybeAdd(
new InvalidClone(
'Cannot clone ' . $invalid_clones[0],
new CodeLocation($statements_analyzer->getSource(), $stmt)
$location
),
$statements_analyzer->getSuppressedIssues()
);
Expand Down
24 changes: 24 additions & 0 deletions tests/DeprecatedAnnotationTest.php
Expand Up @@ -26,6 +26,16 @@ public static function barBar(): void {
}
}',
],
'deprecatedCloneMethod' => [
'code' => '<?php
class Foo {
/**
* @deprecated
*/
public function __clone() {
}
}',
],
'deprecatedClassUsedInsideClass' => [
'code' => '<?php
/**
Expand Down Expand Up @@ -114,6 +124,20 @@ public static function barBar(): void {
Foo::barBar();',
'error_message' => 'DeprecatedMethod',
],
'deprecatedCloneMethodWithCall' => [
'code' => '<?php
class Foo {
/**
* @deprecated
*/
public function __clone() {
}
}
$a = new Foo;
$aa = clone $a;',
'error_message' => 'DeprecatedMethod',
],
'deprecatedClassWithStaticCall' => [
'code' => '<?php
/**
Expand Down
22 changes: 22 additions & 0 deletions tests/InternalAnnotationTest.php
Expand Up @@ -586,6 +586,28 @@ public function batBat(): void {
}',
'error_message' => 'The method A\Foo::barBar is internal to A but called from B\Bat',
],
'internalCloneMethodWithCall' => [
'code' => '<?php
namespace A {
class Foo {
/**
* @internal
*/
public function __clone() {
}
}
}
namespace B {
class Bat {
public function batBat(): void {
$a = new \A\Foo;
$aa = clone $a;
}
}
}',
'error_message' => 'The method A\Foo::__clone is internal to A but called from B\Bat',
],
'internalMethodWithCallFromRootNamespace' => [
'code' => '<?php
namespace A {
Expand Down

0 comments on commit 8b7bc07

Please sign in to comment.