diff --git a/src/main/php/PHPMD/Rule/CleanCode/UndefinedVariable.php b/src/main/php/PHPMD/Rule/CleanCode/UndefinedVariable.php index 960b20c73..af463912e 100644 --- a/src/main/php/PHPMD/Rule/CleanCode/UndefinedVariable.php +++ b/src/main/php/PHPMD/Rule/CleanCode/UndefinedVariable.php @@ -17,6 +17,7 @@ namespace PHPMD\Rule\CleanCode; +use PDepend\Source\AST\ASTArguments; use PDepend\Source\AST\ASTArray; use PDepend\Source\AST\ASTClass; use PDepend\Source\AST\ASTPropertyPostfix; @@ -31,6 +32,8 @@ use PHPMD\Rule\AbstractLocalVariable; use PHPMD\Rule\FunctionAware; use PHPMD\Rule\MethodAware; +use ReflectionException; +use ReflectionFunction; /** * This rule collects all undefined variables within a given function or method @@ -77,9 +80,36 @@ public function apply(AbstractNode $node) $this->addVariableDefinition($variable); } - if (!$this->checkVariableDefined($variable, $node)) { - $this->addViolation($variable, array($this->getVariableImage($variable))); + $this->doCheckVariable($variable, $node); + } + } + + private function doCheckVariable($variable, $node) + { + if (!$this->checkVariableDefined($variable, $node)) { + $parent = $this->getNode($variable->getParent()); + + if ($parent && $parent instanceof ASTArguments) { + $argumentPosition = array_search($this->getNode($variable), $parent->getChildren()); + $function = $this->getNode($parent->getParent()); + $functionName = $function->getImage(); + + try { + $reflectionFunction = new ReflectionFunction($functionName); + $parameters = $reflectionFunction->getParameters(); + + if ($parameters[$argumentPosition]->isPassedByReference()) { + $this->addVariableDefinition($variable); + + return; + } + } catch (ReflectionException $exception) { + // @TODO: Find a way to handle user-land functions + // @TODO: Find a way to handle methods + } } + + $this->addViolation($variable, array($this->getVariableImage($variable))); } }