From 2b67b0f7f319c2265638008a77616400d57689a2 Mon Sep 17 00:00:00 2001 From: Hidde Boomsma Date: Tue, 29 Nov 2016 16:38:48 +0100 Subject: [PATCH] Hostnet ported https://github.com/squizlabs/PHP_CodeSniffer/pull/1219 by Arent --- .../Functions/ReturnTypeDeclarationSniff.php | 157 ++++++++++++++++++ .../ReturnTypeDeclarationUnitTest.1.inc | 74 +++++++++ .../ReturnTypeDeclarationUnitTest.2.inc | 73 ++++++++ .../ReturnTypeDeclarationUnitTest.3.inc | 44 +++++ .../ReturnTypeDeclarationUnitTest.4.inc | 74 +++++++++ .../ReturnTypeDeclarationUnitTest.php | 115 +++++++++++++ 6 files changed, 537 insertions(+) create mode 100644 src/Hostnet/Sniffs/Functions/ReturnTypeDeclarationSniff.php create mode 100644 test/Hostnet/Tests/Functions/ReturnTypeDeclarationUnitTest.1.inc create mode 100644 test/Hostnet/Tests/Functions/ReturnTypeDeclarationUnitTest.2.inc create mode 100644 test/Hostnet/Tests/Functions/ReturnTypeDeclarationUnitTest.3.inc create mode 100644 test/Hostnet/Tests/Functions/ReturnTypeDeclarationUnitTest.4.inc create mode 100644 test/Hostnet/Tests/Functions/ReturnTypeDeclarationUnitTest.php diff --git a/src/Hostnet/Sniffs/Functions/ReturnTypeDeclarationSniff.php b/src/Hostnet/Sniffs/Functions/ReturnTypeDeclarationSniff.php new file mode 100644 index 0000000..d6b5416 --- /dev/null +++ b/src/Hostnet/Sniffs/Functions/ReturnTypeDeclarationSniff.php @@ -0,0 +1,157 @@ +getTokens(); + + $next_separator = $this->getClosingParenthesis($phpcs_file, $tokens, $stack_ptr); + $end_position = $this->getCharacterAfterReturnTypeDeclaration($phpcs_file, $tokens, $stack_ptr); + + $find = [ + T_COLON, + T_RETURN_TYPE, + T_WHITESPACE, + ]; + + $closing_parenthesis_colon_spacing = $this->closing_parenthesis_colon_spacing; + $colon_return_type_spacing = $this->colon_return_type_spacing; + $acc = ''; + while (($next_separator = $phpcs_file->findNext($find, $next_separator + 1, $end_position)) !== false) { + if ($tokens[$next_separator]['code'] === T_COLON) { + $closing_parenthesis_colon_spacing = $acc; + $acc = ''; + } elseif ($tokens[$next_separator]['code'] === T_RETURN_TYPE) { + $colon_return_type_spacing = $acc; + $acc = ''; + if (strtolower($tokens[$next_separator]['content']) !== $tokens[$next_separator]['content']) { + $error = 'All letters in the return type declaration should be lowercase'; + $phpcs_file->addError($error, $stack_ptr); + } + } else { + $acc .= $tokens[$next_separator]['content']; + } + } + + if ($closing_parenthesis_colon_spacing !== $this->closing_parenthesis_colon_spacing + || $colon_return_type_spacing !== $this->colon_return_type_spacing + ) { + $expected = sprintf( + "Expected \")%s:%sreturntype\"", + $this->closing_parenthesis_colon_spacing, + $this->colon_return_type_spacing + ); + $found = sprintf( + "found \")%s:%sreturntype\"", + $closing_parenthesis_colon_spacing, + $colon_return_type_spacing + ); + + $error = $expected . ';' . $found; + + $error = str_replace(["\r\n", "\n", "\r", "\t"], ['\r\n', '\n', '\r', '\t'], $error); + $phpcs_file->addError($error, $stack_ptr); + } + } + + + /** + * Get the position of a function's closing parenthesis within the + * token stack. + * + * @param PHP_CodeSniffer_File $phpcs_file The file being scanned. + * @param array $tokens Token stack for this file + * @param int $stack_ptr The position of the current token + * in the stack passed in $tokens. + * + * @return int position within the token stack + */ + private function getClosingParenthesis(PHP_CodeSniffer_File $phpcs_file, array $tokens, $stack_ptr) + { + $closing_parenthesis = $tokens[$stack_ptr]['parenthesis_closer']; + + // In case the function is a closure, the closing parenthesis + // may be positioned after a use language construct. + if ($tokens[$stack_ptr]['code'] === T_CLOSURE) { + $use = $phpcs_file->findNext(T_USE, ($closing_parenthesis + 1), $tokens[$stack_ptr]['scope_opener']); + if ($use !== false) { + $open_bracket = $phpcs_file->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $closing_parenthesis = $tokens[$open_bracket]['parenthesis_closer']; + } + } + + return $closing_parenthesis; + } + + + /** + * Get the position of first character after the return type declaration + * within the token stack. + * This can be an opening brace, or, in case of an interface, + * a semicolon. + * + * @param PHP_CodeSniffer_File $phpcs_file The file being scanned. + * @param array $tokens Token stack for this file + * @param int $stack_ptr The position of the current token + * in the stack passed in $tokens. + * + * @return int position within the token stack + */ + private function getCharacterAfterReturnTypeDeclaration(PHP_CodeSniffer_File $phpcs_file, array $tokens, $stack_ptr) + { + if (isset($tokens[$stack_ptr]['scope_opener']) === false) { + $end_position = $phpcs_file->findNext(T_SEMICOLON, $stack_ptr); + } else { + $end_position = $tokens[$stack_ptr]['scope_opener']; + } + + return $end_position; + } +} diff --git a/test/Hostnet/Tests/Functions/ReturnTypeDeclarationUnitTest.1.inc b/test/Hostnet/Tests/Functions/ReturnTypeDeclarationUnitTest.1.inc new file mode 100644 index 0000000..484bafb --- /dev/null +++ b/test/Hostnet/Tests/Functions/ReturnTypeDeclarationUnitTest.1.inc @@ -0,0 +1,74 @@ + + * @author Marc McIntyre + * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @link http://pear.php.net/package/PHP_CodeSniffer + */ + +/** + * Unit test class for the ReturnTypeDeclaration sniff. + * + * A sniff unit test checks a .inc file for expected violations of a single + * coding standard. Expected errors and warnings are stored in this class. + * + * @category PHP + * @package PHP_CodeSniffer + * @author Arent van Korlaar + * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class Hostnet_Tests_Functions_ReturnTypeDeclarationUnitTest extends Hostnet_Tests_AbstractPHPCSBridge +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList($test_file = '') + { + switch ($test_file) { + case 'ReturnTypeDeclarationUnitTest.1.inc': + return array( + 17 => 1, + 22 => 1, + 27 => 1, + 32 => 1, + 37 => 1, + 42 => 1, + 47 => 1, + 53 => 1, + 59 => 1, + 65 => 1, + ); + case 'ReturnTypeDeclarationUnitTest.2.inc': + return array( + 17 => 1, + 22 => 1, + 27 => 1, + 32 => 1, + 37 => 1, + 42 => 1, + 47 => 1, + 53 => 1, + 59 => 1, + 65 => 1, + ); + case 'ReturnTypeDeclarationUnitTest.3.inc': + return array( + 14 => 1, + 16 => 1, + 18 => 1, + 20 => 1, + 23 => 1, + 26 => 1, + 29 => 1, + 33 => 1, + 37 => 1, + 41 => 1, + ); + case 'ReturnTypeDeclarationUnitTest.4.inc': + return array( + 17 => 1, + 22 => 1, + 27 => 1, + 32 => 1, + 37 => 1, + 42 => 1, + 47 => 1, + 53 => 1, + 59 => 1, + 65 => 1, + ); + default: + return array(); + }//end switch + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return array(); + }//end getWarningList() +}//end class