Skip to content

Instantly share code, notes, and snippets.

@nulpatrol
Created September 21, 2021 05:59
Show Gist options
  • Save nulpatrol/1eb05c7f785980de300d032e3bd05fa3 to your computer and use it in GitHub Desktop.
Save nulpatrol/1eb05c7f785980de300d032e3bd05fa3 to your computer and use it in GitHub Desktop.
<?php
declare(strict_types=1);
namespace Rost\Rules;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
class DetectCopyOnWrite implements Rule
{
public function getNodeType(): string
{
return Node\Expr\Assign::class;
}
public function processNode(Node $node, Scope $scope): array
{
$messages = [];
/** @var Node\Expr\Assign $node */
$assignAcceptor = $node->var;
if ($assignAcceptor instanceof Node\Expr\ArrayDimFetch) {
/** @var Node\Expr\Variable $variable */
$variable = $assignAcceptor->var;
$currentFunctionParameters = $this->getCurrentFunctionParameters($scope);
if (in_array($variable->name, $currentFunctionParameters)) {
$messages[] = 'Function argument mutation found. It can cause memory problems, because of copy on write principle';
}
}
return $messages;
}
private function getCurrentFunctionParameters(Scope $scope): array
{
$parameters = [];
if ($scope->isInAnonymousFunction()) {
$functionParameters = $scope->getAnonymousFunctionReflection()->getParameters();
foreach ($functionParameters as $parameter) {
$parameters[] = $parameter->getName();
}
} else {
$functionVariants = $scope->getFunction()->getVariants();
foreach ($functionVariants as $functionVariant) {
foreach ($functionVariant->getParameters() as $functionParameter) {
$parameters[] = $functionParameter->getName();
}
}
}
return $parameters;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment