diff --git a/Universal/Docs/PHP/RequireExitDieParenthesesStandard.xml b/Universal/Docs/PHP/RequireExitDieParenthesesStandard.xml new file mode 100644 index 0000000..677a4ce --- /dev/null +++ b/Universal/Docs/PHP/RequireExitDieParenthesesStandard.xml @@ -0,0 +1,25 @@ + + + + + + + + (); +exit($status); + ]]> + + + ; +exit; + ]]> + + + diff --git a/Universal/Sniffs/PHP/RequireExitDieParenthesesSniff.php b/Universal/Sniffs/PHP/RequireExitDieParenthesesSniff.php new file mode 100644 index 0000000..47ce20a --- /dev/null +++ b/Universal/Sniffs/PHP/RequireExitDieParenthesesSniff.php @@ -0,0 +1,85 @@ + + */ + public function register() + { + return [\T_EXIT]; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 1.5.0 + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + // Live coding. Do not flag (yet). + return; + } + + if ($tokens[$nextNonEmpty]['code'] === \T_OPEN_PARENTHESIS) { + // Parentheses found. + $phpcsFile->recordMetric($stackPtr, self::METRIC_NAME, 'yes'); + return; + } + + $phpcsFile->recordMetric($stackPtr, self::METRIC_NAME, 'no'); + + $fix = $phpcsFile->addFixableError( + 'Parentheses required when calling %s, even if no argument is given.', + $stackPtr, + 'Missing', + [\strtolower(\ltrim($tokens[$stackPtr]['content'], '\\'))] + ); + + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, '()'); + } + } +} diff --git a/Universal/Tests/PHP/RequireExitDieParenthesesUnitTest.1.inc b/Universal/Tests/PHP/RequireExitDieParenthesesUnitTest.1.inc new file mode 100644 index 0000000..f2828c4 --- /dev/null +++ b/Universal/Tests/PHP/RequireExitDieParenthesesUnitTest.1.inc @@ -0,0 +1,54 @@ +exit; + echo $this->die; + echo $this->exit(); + echo $this->die(); + } +} + +// Invalid PHP, but not our concern. Not our target. +namespace\Sub\exit; +Partially\Qualified\die; +\Fully\Qualified\exit; + +/* + * OK. + */ +exit(); +die(); +Exit(); +DIE(); +\exit(); +\die(); +exit ($status); +\die /*comment*/ (10); + +/* + * Bad. + */ +exit; +die; +EXIT; +Die; +\exit; +\die; diff --git a/Universal/Tests/PHP/RequireExitDieParenthesesUnitTest.1.inc.fixed b/Universal/Tests/PHP/RequireExitDieParenthesesUnitTest.1.inc.fixed new file mode 100644 index 0000000..a00c890 --- /dev/null +++ b/Universal/Tests/PHP/RequireExitDieParenthesesUnitTest.1.inc.fixed @@ -0,0 +1,54 @@ +exit; + echo $this->die; + echo $this->exit(); + echo $this->die(); + } +} + +// Invalid PHP, but not our concern. Not our target. +namespace\Sub\exit; +Partially\Qualified\die; +\Fully\Qualified\exit; + +/* + * OK. + */ +exit(); +die(); +Exit(); +DIE(); +\exit(); +\die(); +exit ($status); +\die /*comment*/ (10); + +/* + * Bad. + */ +exit(); +die(); +EXIT(); +Die(); +\exit(); +\die(); diff --git a/Universal/Tests/PHP/RequireExitDieParenthesesUnitTest.2.inc b/Universal/Tests/PHP/RequireExitDieParenthesesUnitTest.2.inc new file mode 100644 index 0000000..33e4c94 --- /dev/null +++ b/Universal/Tests/PHP/RequireExitDieParenthesesUnitTest.2.inc @@ -0,0 +1,6 @@ + Key is the line number, value is the number of expected errors. + */ + public function getErrorList($testFile = '') + { + switch ($testFile) { + case 'RequireExitDieParenthesesUnitTest.1.inc': + return [ + 49 => 1, + 50 => 1, + 51 => 1, + 52 => 1, + 53 => 1, + 54 => 1, + ]; + + default: + return []; + } + } + + /** + * Returns the lines where warnings should occur. + * + * @return array Key is the line number, value is the number of expected warnings. + */ + public function getWarningList() + { + return []; + } +}