Skip to content

Commit

Permalink
Detect $object->$method() and $object->${'method'}(), also static calls
Browse files Browse the repository at this point in the history
  • Loading branch information
spaze committed Dec 7, 2024
1 parent f3f41e5 commit e4e3341
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 3 deletions.
14 changes: 11 additions & 3 deletions src/RuleErrors/DisallowedMethodRuleErrors.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PhpParser\Node\Expr\CallLike;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PHPStan\Analyser\Scope;
Expand Down Expand Up @@ -49,13 +50,20 @@ public function __construct(
*/
public function get($class, CallLike $node, Scope $scope, array $disallowedCalls): array
{
if (!isset($node->name) || !($node->name instanceof Identifier)) {
if ($node->name instanceof Identifier) {
$methodName = $node->name->name;
} elseif ($node->name instanceof Variable) {
$methodName = $this->typeResolver->getVariableStringValue($node->name, $scope);
if (!is_string($methodName)) {
return [];
}
} else {
return [];
}

$calledOnType = $this->typeResolver->getType($class, $scope);
if ($calledOnType->canCallMethods()->yes() && $calledOnType->hasMethod($node->name->name)->yes()) {
$method = $calledOnType->getMethod($node->name->name, $scope);
if ($calledOnType->canCallMethods()->yes() && $calledOnType->hasMethod($methodName)->yes()) {
$method = $calledOnType->getMethod($methodName, $scope);
$declaringClass = $method->getDeclaringClass();
$classes = $calledOnType->getObjectClassReflections();
$classNames = array_map(fn($class): string => $class->isAnonymous() ? 'class@anonymous' : $class->getName(), $classes);
Expand Down
8 changes: 8 additions & 0 deletions tests/Calls/MethodCallsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,14 @@ public function testRule(): void
'Calling Inheritance\Base::x() (as class@anonymous::x()) is forbidden, Base::x*() methods are dangerous. [Inheritance\Base::x() matches Inheritance\Base::x*()]',
91,
],
[
"Calling Waldo\Quux\Blade::runner() is forbidden, I've seen tests you people wouldn't believe. [Waldo\Quux\Blade::runner() matches Waldo\Quux\Blade::run*()]",
95,
],
[
"Calling Waldo\Quux\Blade::runner() is forbidden, I've seen tests you people wouldn't believe. [Waldo\Quux\Blade::runner() matches Waldo\Quux\Blade::run*()]",
96,
],
]);
$this->analyse([__DIR__ . '/../src/disallowed-allow/methodCalls.php'], [
[
Expand Down
8 changes: 8 additions & 0 deletions tests/Calls/StaticCallsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,14 @@ public function testRule(): void
'Calling Inheritance\Base::woofer() (as class@anonymous::woofer()) is forbidden, method Base::woofer() is dangerous. [Inheritance\Base::woofer() matches Inheritance\Base::w*f*r()]',
57,
],
[
'Calling Fiction\Pulp\Royale::withCheese() is forbidden, a Quarter Pounder with Cheese?',
60,
],
[
'Calling Fiction\Pulp\Royale::withCheese() is forbidden, a Quarter Pounder with Cheese?',
61,
],
]);
$this->analyse([__DIR__ . '/../src/disallowed-allow/staticCalls.php'], [
[
Expand Down
5 changes: 5 additions & 0 deletions tests/src/disallowed-allow/methodCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,8 @@ public static function y(): void
// allowed by path
$foo = new class extends Inheritance\Base {};
$foo->x();

// dynamic method name allowed by path and only with these params
$method = 'runner';
$blade->$method(42, true, '909');
$blade->${'method'}(42, true, '909');
4 changes: 4 additions & 0 deletions tests/src/disallowed-allow/staticCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,7 @@ public static function y(): void
// allowed by path
$foo = new class extends Inheritance\Base {};
$foo::woofer();

$method = 'withCheese';
Pulp\Royale::$method();
Pulp\Royale::${'method'}();
5 changes: 5 additions & 0 deletions tests/src/disallowed/methodCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,8 @@ public static function y(): void
// disallowed parent method
$foo = new class extends Inheritance\Base {};
$foo->x();

// disallowed dynamic method name
$method = 'runner';
$blade->$method(42, true, '909');
$blade->${'method'}(42, true, '909');
4 changes: 4 additions & 0 deletions tests/src/disallowed/staticCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,7 @@ public static function y(): void
// disallowed parent method
$foo = new class extends Inheritance\Base {};
$foo::woofer();

$method = 'withCheese';
Pulp\Royale::$method();
Pulp\Royale::${'method'}();

0 comments on commit e4e3341

Please sign in to comment.