Skip to content

Commit

Permalink
Improve CompactVariablesRule - recognize array parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Feb 1, 2021
1 parent 2a75a25 commit f2dd33a
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 14 deletions.
52 changes: 38 additions & 14 deletions src/Rules/Variables/CompactVariablesRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Constant\ConstantStringType;
use PHPStan\Type\Type;

/**
* @implements \PHPStan\Rules\Rule<\PhpParser\Node\Expr\FuncCall>
Expand Down Expand Up @@ -43,25 +45,47 @@ public function processNode(Node $node, Scope $scope): array

foreach ($functionArguments as $argument) {
$argumentType = $scope->getType($argument->value);
if (!$argumentType instanceof ConstantStringType) {
continue;
}
$constantStrings = $this->findConstantStrings($argumentType);
foreach ($constantStrings as $constantString) {
$variableName = $constantString->getValue();
$scopeHasVariable = $scope->hasVariableType($variableName);

$variableName = $argumentType->getValue();
$scopeHasVariable = $scope->hasVariableType($variableName);

if ($scopeHasVariable->no()) {
$messages[] = RuleErrorBuilder::message(
sprintf('Call to function compact() contains undefined variable $%s.', $variableName)
)->line($argument->getLine())->build();
} elseif ($this->checkMaybeUndefinedVariables && $scopeHasVariable->maybe()) {
$messages[] = RuleErrorBuilder::message(
sprintf('Call to function compact() contains possibly undefined variable $%s.', $variableName)
)->line($argument->getLine())->build();
if ($scopeHasVariable->no()) {
$messages[] = RuleErrorBuilder::message(
sprintf('Call to function compact() contains undefined variable $%s.', $variableName)
)->line($argument->getLine())->build();
} elseif ($this->checkMaybeUndefinedVariables && $scopeHasVariable->maybe()) {
$messages[] = RuleErrorBuilder::message(
sprintf('Call to function compact() contains possibly undefined variable $%s.', $variableName)
)->line($argument->getLine())->build();
}
}
}

return $messages;
}

/**
* @param Type $type
* @return array<int, ConstantStringType>
*/
private function findConstantStrings(Type $type): array
{
if ($type instanceof ConstantStringType) {
return [$type];
}

if ($type instanceof ConstantArrayType) {
$result = [];
foreach ($type->getValueTypes() as $valueType) {
$constantStrings = $this->findConstantStrings($valueType);
$result = array_merge($result, $constantStrings);
}

return $result;
}

return [];
}

}
4 changes: 4 additions & 0 deletions tests/PHPStan/Rules/Variables/CompactVariablesRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public function testCompactVariables(): void
'Call to function compact() contains possibly undefined variable $baz.',
23,
],
[
'Call to function compact() contains undefined variable $foo.',
29,
],
]);
}

Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/Rules/Variables/data/compact-variables.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@ public function doFoo(string $foo): array
'baz'
);
}

public function doBar(): void
{
compact([[['foo']]]);
}
}

0 comments on commit f2dd33a

Please sign in to comment.