diff --git a/src/lint/linter/ArcanistXHPASTLinter.php b/src/lint/linter/ArcanistXHPASTLinter.php --- a/src/lint/linter/ArcanistXHPASTLinter.php +++ b/src/lint/linter/ArcanistXHPASTLinter.php @@ -47,6 +47,7 @@ const LINT_PHP_COMPATIBILITY = 45; const LINT_LANGUAGE_CONSTRUCT_PAREN = 46; const LINT_EMPTY_STATEMENT = 47; + const LINT_CALL_TIME_PASS_BY_REF = 48; private $naminghook; private $switchhook; @@ -105,6 +106,7 @@ self::LINT_PHP_COMPATIBILITY => 'PHP Compatibility', self::LINT_LANGUAGE_CONSTRUCT_PAREN => 'Language Construct Parentheses', self::LINT_EMPTY_STATEMENT => 'Empty Block Statement', + self::LINT_CALL_TIME_PASS_BY_REF => 'Call-Time Pass-By-Reference', ); } @@ -193,7 +195,7 @@ public function getVersion() { // The version number should be incremented whenever a new rule is added. - return '8'; + return '9'; } protected function resolveFuture($path, Future $future) { @@ -263,6 +265,7 @@ 'lintPHPCompatibility' => self::LINT_PHP_COMPATIBILITY, 'lintLanguageConstructParentheses' => self::LINT_LANGUAGE_CONSTRUCT_PAREN, 'lintEmptyBlockStatements' => self::LINT_EMPTY_STATEMENT, + 'lintCallTimePassByReference' => self::LINT_CALL_TIME_PASS_BY_REF, ); foreach ($method_codes as $method => $codes) { @@ -2714,6 +2717,21 @@ } } + protected function lintCallTimePassByReference(XHPASTNode $root) { + $nodes = $root->selectDescendantsOfType('n_CALL_PARAMETER_LIST'); + + foreach ($nodes as $node) { + $parameters = $node->selectDescendantsOfType('n_VARIABLE_REFERENCE'); + + foreach ($parameters as $parameter) { + $this->raiseLintAtNode( + $parameter, + self::LINT_CALL_TIME_PASS_BY_REF, + pht('Call-time pass-by-reference calls are prohibited.')); + } + } + } + public function getSuperGlobalNames() { return array( '$GLOBALS', diff --git a/src/lint/linter/__tests__/xhpast/call-time-pass-by-reference.lint-test b/src/lint/linter/__tests__/xhpast/call-time-pass-by-reference.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/xhpast/call-time-pass-by-reference.lint-test @@ -0,0 +1,29 @@ +myfunc(&$myvar); +$this->myfunc($myvar); + +MyClass::myfunc(&$myvar); +MyClass::myfunc($myvar); + +while (testfunc($var1, &$var2, $var3, &$var4) === false) {} + +sprintf('0%o', 0777 & $p); + +$foo(&$myvar); +~~~~~~~~~~ +error:9:8 +error:12:15 +error:15:17 +error:18:24 +error:18:39 +error:22:6