From ed2bd7d588f3616dbe20bbfbbc98dfedac3b45f3 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 13 Nov 2016 23:33:41 +0000 Subject: [PATCH 001/225] Zend Framework Coding Standard - extended PSR-2. More Sniffs. --- .gitignore | 2 + ZendCodingStandard/CodingStandard.php | 35 ++ .../Sniffs/Arrays/TrailingArrayCommaSniff.php | 71 +++ .../Classes/UnusedUseStatementSniff.php | 194 ++++++ .../Sniffs/Commenting/DocCommentSniff.php | 155 +++++ .../Commenting/FunctionCommentSniff.php | 594 ++++++++++++++++++ .../Commenting/VariableCommentSniff.php | 160 +++++ .../Sniffs/Methods/LineAfterSniff.php | 68 ++ .../ValidVariableNameSniff.php | 73 +++ .../Sniffs/PHP/TypeCastingSniff.php | 117 ++++ .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 120 ++++ ZendCodingStandard/ruleset.xml | 75 +++ composer.json | 12 +- phpcs.xml | 6 + ruleset.xml | 21 +- 15 files changed, 1682 insertions(+), 21 deletions(-) create mode 100644 .gitignore create mode 100644 ZendCodingStandard/CodingStandard.php create mode 100644 ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php create mode 100644 ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php create mode 100644 ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php create mode 100644 ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php create mode 100644 ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php create mode 100644 ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php create mode 100644 ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php create mode 100644 ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php create mode 100644 ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php create mode 100644 ZendCodingStandard/ruleset.xml create mode 100644 phpcs.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..d1502b08 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +vendor/ +composer.lock diff --git a/ZendCodingStandard/CodingStandard.php b/ZendCodingStandard/CodingStandard.php new file mode 100644 index 00000000..23f88646 --- /dev/null +++ b/ZendCodingStandard/CodingStandard.php @@ -0,0 +1,35 @@ +getTokens(); + $arrayToken = $tokens[$stackPtr]; + $closeParenthesisPointer = $arrayToken['bracket_closer']; + $openParenthesisToken = $tokens[$arrayToken['bracket_opener']]; + $closeParenthesisToken = $tokens[$closeParenthesisPointer]; + + if ($openParenthesisToken['line'] === $closeParenthesisToken['line']) { + return; + } + + $previousToCloseParenthesisPointer = $phpcsFile->findPrevious( + [ + T_WHITESPACE, + T_COMMENT, + T_DOC_COMMENT, + T_DOC_COMMENT_OPEN_TAG, + T_DOC_COMMENT_CLOSE_TAG, + T_DOC_COMMENT_STAR, + T_DOC_COMMENT_STRING, + T_DOC_COMMENT_TAG, + T_DOC_COMMENT_WHITESPACE, + ], + $closeParenthesisPointer - 1, + null, + true + ); + + $previousToCloseParenthesisToken = $tokens[$previousToCloseParenthesisPointer]; + + if ($previousToCloseParenthesisToken['code'] !== T_COMMA + && $previousToCloseParenthesisToken['code'] !== T_OPEN_SHORT_ARRAY + && $closeParenthesisToken['line'] !== $previousToCloseParenthesisToken['line'] + ) { + $fix = $phpcsFile->addFixableError( + 'Multiline arrays must have a trailing comma after the last element', + $previousToCloseParenthesisPointer + ); + + if ($fix) { + $phpcsFile->fixer->addContent($previousToCloseParenthesisPointer, ','); + } + } + } +} diff --git a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php new file mode 100644 index 00000000..9abaf9c0 --- /dev/null +++ b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php @@ -0,0 +1,194 @@ + + * @copyright 2016 Capstone Digital + */ +class UnusedUseStatementSniff implements PHP_CodeSniffer_Sniff +{ + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_USE]; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param PHP_CodeSniffer_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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Only check use statements in the global scope. + if (! empty($tokens[$stackPtr]['conditions'])) { + return; + } + + // Seek to the end of the statement and get the string before the semi colon. + $semiColon = $phpcsFile->findEndOfStatement($stackPtr); + if ($tokens[$semiColon]['code'] !== T_SEMICOLON) { + return; + } + + $classPtr = $phpcsFile->findPrevious( + PHP_CodeSniffer_Tokens::$emptyTokens, + ($semiColon - 1), + null, + true + ); + + if ($tokens[$classPtr]['code'] !== T_STRING) { + return; + } + + // Search where the class name is used. PHP treats class names case + // insensitive, that's why we cannot search for the exact class name string + // and need to iterate over all T_STRING tokens in the file. + $classUsed = $phpcsFile->findNext([T_STRING, T_DOC_COMMENT_STRING], ($classPtr + 1)); + $className = $tokens[$classPtr]['content']; + $lowerClassName = strtolower($className); + + // Check if the referenced class is in the same namespace as the current + // file. If it is then the use statement is not necessary. + $namespacePtr = $phpcsFile->findPrevious([T_NAMESPACE], $stackPtr); + + // Check if the use statement does aliasing with the "as" keyword. Aliasing + // is allowed even in the same namespace. + $aliasUsed = $phpcsFile->findPrevious(T_AS, ($classPtr - 1), $stackPtr); + + if ($namespacePtr !== false && $aliasUsed === false) { + $nsEnd = $phpcsFile->findNext( + [ + T_NS_SEPARATOR, + T_STRING, + T_DOC_COMMENT_STRING, + T_WHITESPACE, + ], + ($namespacePtr + 1), + null, + true + ); + $namespace = trim($phpcsFile->getTokensAsString(($namespacePtr + 1), ($nsEnd - $namespacePtr - 1))); + + $useNamespacePtr = $phpcsFile->findNext([T_STRING], ($stackPtr + 1)); + $useNamespaceEnd = $phpcsFile->findNext( + [ + T_NS_SEPARATOR, + T_STRING, + ], + ($useNamespacePtr + 1), + null, + true + ); + $useNamespace = rtrim( + $phpcsFile->getTokensAsString( + $useNamespacePtr, + ($useNamespaceEnd - $useNamespacePtr - 1) + ), + '\\' + ); + + if (strcasecmp($namespace, $useNamespace) === 0) { + $classUsed = false; + } + } + + $emptyTokens = PHP_CodeSniffer_Tokens::$emptyTokens; + unset($emptyTokens[T_DOC_COMMENT_TAG]); + + + while ($classUsed !== false) { + if (($tokens[$classUsed]['code'] == T_STRING + && strtolower($tokens[$classUsed]['content']) === $lowerClassName) + || ($tokens[$classUsed]['code'] == T_DOC_COMMENT_STRING + && preg_match( + '/(\s|\||^)' . preg_quote($lowerClassName) . '(\s|\||$|\[\])/i', + $tokens[$classUsed]['content'] + )) + ) { + $beforeUsage = $phpcsFile->findPrevious( + $emptyTokens, + ($classUsed - 1), + null, + true + ); + + if ($tokens[$classUsed]['code'] == T_STRING) { + // If a backslash is used before the class name then this is some other + // use statement. + if ($tokens[$beforeUsage]['code'] !== T_USE + && $tokens[$beforeUsage]['code'] !== T_NS_SEPARATOR + ) { + return; + } + + // Trait use statement within a class. + if ($tokens[$beforeUsage]['code'] === T_USE + && ! empty($tokens[$beforeUsage]['conditions']) + ) { + return; + } + } else { + if ($tokens[$beforeUsage]['code'] === T_DOC_COMMENT_TAG && + in_array( + $tokens[$beforeUsage]['content'], + ['@var', '@param', '@return', '@throws', '@method'] + ) + ) { + return; + } + } + } + + $classUsed = $phpcsFile->findNext([T_STRING, T_DOC_COMMENT_STRING], ($classUsed + 1)); + } + + $warning = 'Unused use statement: ' . $className; + $fix = $phpcsFile->addFixableWarning($warning, $stackPtr, 'UnusedUse'); + + if ($fix) { + // Remove the whole use statement line. + $phpcsFile->fixer->beginChangeset(); + for ($i = $stackPtr; $i <= $semiColon; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // Also remove whitespace after the semicolon (new lines). + while (isset($tokens[$i]) && $tokens[$i]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($i, ''); + if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false) { + break; + } + + ++$i; + } + + $phpcsFile->fixer->endChangeset(); + } + } +} diff --git a/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php new file mode 100644 index 00000000..0543ad0b --- /dev/null +++ b/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -0,0 +1,155 @@ +getTokens(); + $commentStart = $stackPtr; + $commentEnd = $tokens[$stackPtr]['comment_closer']; + + if ($tokens[$commentStart]['line'] == $tokens[$commentEnd]['line']) { + return; + } + + $short = $phpcsFile->findNext( + [ + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STAR, + ], + $stackPtr + 1, + $commentEnd, + true + ); + if ($short === false) { + // No content at all. + $error = 'Doc comment is empty.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty'); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $commentStart; $i <= $commentEnd; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->endChangeset(); + } + + return; + } + + if ($tokens[$commentEnd + 1]['content'] !== "\n") { + $error = 'The close comment tag must be the only content on the line.'; + $fix = $phpcsFile->addFixableError($error, $commentEnd); + + if ($fix) { + $phpcsFile->fixer->addNewline($commentEnd); + } + + return; + } + + $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_WHITESPACE], $commentEnd - 1, null, true); + if ($tokens[$prev]['content'] !== "\n" + && $tokens[$prev]['line'] === $tokens[$commentEnd]['line'] + ) { + $error = 'The close comment tag must be the only content on the line.'; + $fix = $phpcsFile->addFixableError($error, $commentEnd); + + if ($fix) { + $phpcsFile->fixer->addNewlineBefore($commentEnd); + } + } + + if ($tokens[$commentEnd + 2]['content'] === "\n") { + // There is empty line after doc block. + $before = $tokens[$commentStart - 1]; + + $indent = $before['code'] == T_OPEN_TAG || $before['content'] == "\n" + ? 0 + : strlen($before['content']); + } elseif ($tokens[$commentEnd + 2]['code'] == T_WHITESPACE) { + $indent = strlen($tokens[$commentEnd + 2]['content']); + } else { + $indent = 0; + } + + // First line of the doc comment. + $spaces = $tokens[$commentStart - 1]; + if ($spaces['code'] === T_WHITESPACE + && $spaces['content'] !== "\n" + && strlen($spaces['content']) !== $indent + ) { + $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; + $data = [ + $indent, + strlen($spaces['content']), + ]; + $fix = $phpcsFile->addFixableError($error, $commentStart, null, $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($commentStart - 1, str_repeat(' ', $indent)); + } + } elseif ($spaces['code'] === T_WHITESPACE + && $spaces['content'] === "\n" + && $indent > 0 + ) { + $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; + $data = [ + $indent, + 0, + ]; + $fix = $phpcsFile->addFixableError($error, $commentStart, null, $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($commentStart - 1, "\n" . str_repeat(' ', $indent)); + } + } + + // Rest of the doc comment. + $from = $commentStart; + $search = [T_DOC_COMMENT_STAR, T_DOC_COMMENT_CLOSE_TAG]; + while ($next = $phpcsFile->findNext($search, $from + 1, $commentEnd + 1)) { + $spaces = $tokens[$next - 1]; + + if ($spaces['content'] == "\n") { + $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; + $data = [ + $indent + 1, + 0, + ]; + $fix = $phpcsFile->addFixableError($error, $next, null, $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($next - 1, "\n" . ' '); + } + } elseif ($spaces['code'] == T_DOC_COMMENT_WHITESPACE + && strlen($spaces['content']) !== $indent + 1 + ) { + $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; + $data = [ + $indent + 1, + strlen($spaces['content']), + ]; + $fix = $phpcsFile->addFixableError($error, $next, null, $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($next - 1, str_repeat(' ', $indent + 1)); + } + } + + $from = $next; + } + } +} diff --git a/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php new file mode 100644 index 00000000..cf7b078c --- /dev/null +++ b/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -0,0 +1,594 @@ + + * @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 + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class FunctionCommentSniff extends PEAR_Sniffs_Commenting_FunctionCommentSniff +{ + /** + * The current PHP version. + * + * @var int + */ + private $phpVersion; + + /** + * Process the return comment of this function comment. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processReturn(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + // Skip constructor and destructor. + $methodName = $phpcsFile->getDeclarationName($stackPtr); + $isSpecialMethod = $methodName === '__construct' || $methodName === '__destruct'; + + $return = null; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@return') { + if ($return !== null) { + $error = 'Only 1 @return tag is allowed in a function comment'; + $phpcsFile->addError($error, $tag, 'DuplicateReturn'); + return; + } + + $return = $tag; + } + } + + if ($isSpecialMethod === true) { + return; + } + + if ($return !== null) { + $content = $tokens[($return + 2)]['content']; + if (empty($content) || $tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) { + $error = 'Return type missing for @return tag in function comment'; + $phpcsFile->addError($error, $return, 'MissingReturnType'); + } else { + // Check return type (can be multiple, separated by '|'). + $typeNames = explode('|', $content); + $suggestedNames = []; + foreach ($typeNames as $i => $typeName) { + $suggestedName = CodingStandard::suggestType($typeName); + if (in_array($suggestedName, $suggestedNames) === false) { + $suggestedNames[] = $suggestedName; + } + } + + $suggestedType = implode('|', $suggestedNames); + if ($content !== $suggestedType) { + $error = 'Expected "%s" but found "%s" for function return type'; + $data = [ + $suggestedType, + $content, + ]; + $fix = $phpcsFile->addFixableError($error, $return, 'InvalidReturn', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken(($return + 2), $suggestedType); + } + } + + // Support both a return type and a description. The return type + // is anything up to the first space. + $returnParts = explode(' ', $content, 2); + $returnType = $returnParts[0]; + + // If the return type is void, make sure there is + // no return statement in the function. + if ($returnType === 'void') { + if (isset($tokens[$stackPtr]['scope_closer'])) { + $endToken = $tokens[$stackPtr]['scope_closer']; + for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) { + if ($tokens[$returnToken]['code'] === T_CLOSURE) { + $returnToken = $tokens[$returnToken]['scope_closer']; + continue; + } + + if ($tokens[$returnToken]['code'] === T_RETURN + || $tokens[$returnToken]['code'] === T_YIELD + ) { + break; + } + } + + if ($returnToken !== $endToken) { + // If the function is not returning anything, just + // exiting, then there is no problem. + $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); + if ($tokens[$semicolon]['code'] !== T_SEMICOLON) { + $error = 'Function return type is void, but function contains return statement'; + $phpcsFile->addError($error, $return, 'InvalidReturnVoid'); + } + } + }//end if + } elseif ($returnType !== 'mixed') { + $returnTypes = explode('|', $returnType); + + // If return type is not void, there needs to be a return statement + // somewhere in the function that returns something. + + // If "void" is not also in one of the return types. + if (! in_array('void', $returnTypes) + && isset($tokens[$stackPtr]['scope_closer']) + ) { + $endToken = $tokens[$stackPtr]['scope_closer']; + $returnToken = $phpcsFile->findNext([T_RETURN, T_YIELD], $stackPtr, $endToken); + if ($returnToken === false) { + $error = 'Function return type is not void, but function has no return statement'; + $phpcsFile->addError($error, $return, 'InvalidNoReturn'); + } else { + $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); + if ($tokens[$semicolon]['code'] === T_SEMICOLON) { + $error = 'Function return type is not void, but function is returning void here'; + $phpcsFile->addError($error, $returnToken, 'InvalidReturnNotVoid'); + } + } + } + } + } + } else { + $error = 'Missing @return tag in function comment'; + $phpcsFile->addError($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn'); + } + } + + /** + * Process any throw tags that this function comment has. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processThrows(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + $throws = []; + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($tokens[$tag]['content'] !== '@throws') { + continue; + } + + $exception = null; + $comment = null; + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[($tag + 2)]['content'], $matches); + $exception = $matches[1]; + if (isset($matches[2]) && trim($matches[2]) !== '') { + $comment = $matches[2]; + } + } + + if ($exception === null) { + $error = 'Exception type and comment missing for @throws tag in function comment'; + $phpcsFile->addError($error, $tag, 'InvalidThrows'); + } elseif ($comment === null) { + $error = 'Comment missing for @throws tag in function comment'; + $phpcsFile->addError($error, $tag, 'EmptyThrows'); + } else { + // Any strings until the next tag belong to this comment. + if (isset($tokens[$commentStart]['comment_tags'][$pos + 1])) { + $end = $tokens[$commentStart]['comment_tags'][$pos + 1]; + } else { + $end = $tokens[$commentStart]['comment_closer']; + } + + for ($i = $tag + 3; $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + $comment .= ' ' . $tokens[$i]['content']; + } + } + + // Starts with a capital letter and ends with a fullstop. + $firstChar = $comment{0}; + if (strtoupper($firstChar) !== $firstChar) { + $error = '@throws tag comment must start with a capital letter'; + $phpcsFile->addError($error, ($tag + 2), 'ThrowsNotCapital'); + } + + $lastChar = substr($comment, -1); + if ($lastChar !== '.') { + $error = '@throws tag comment must end with a full stop'; + $phpcsFile->addError($error, ($tag + 2), 'ThrowsNoFullStop'); + } + } + } + } + + /** + * Process the function parameter comments. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart) + { + if (! $this->phpVersion) { + $this->phpVersion = PHP_CodeSniffer::getConfigData('php_version'); + if (! $this->phpVersion) { + $this->phpVersion = PHP_VERSION_ID; + } + } + + $tokens = $phpcsFile->getTokens(); + + $params = []; + $maxType = 0; + $maxVar = 0; + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($tokens[$tag]['content'] !== '@param') { + continue; + } + + $type = ''; + $typeSpace = 0; + $var = ''; + $varSpace = 0; + $comment = ''; + $commentLines = []; + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match( + '/([^$&.]+)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', + $tokens[($tag + 2)]['content'], + $matches + ); + + if (! empty($matches)) { + $typeLen = strlen($matches[1]); + $type = trim($matches[1]); + $typeSpace = ($typeLen - strlen($type)); + $typeLen = strlen($type); + if ($typeLen > $maxType) { + $maxType = $typeLen; + } + } + + if (isset($matches[2])) { + $var = $matches[2]; + $varLen = strlen($var); + if ($varLen > $maxVar) { + $maxVar = $varLen; + } + + if (isset($matches[4])) { + $varSpace = strlen($matches[3]); + $comment = $matches[4]; + $commentLines[] = [ + 'comment' => $comment, + 'token' => ($tag + 2), + 'indent' => $varSpace, + ]; + + // Any strings until the next tag belong to this comment. + if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)])) { + $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; + } else { + $end = $tokens[$commentStart]['comment_closer']; + } + + for ($i = $tag + 3; $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + $indent = 0; + if ($tokens[$i - 1]['code'] === T_DOC_COMMENT_WHITESPACE) { + $indent = strlen($tokens[($i - 1)]['content']); + } + + $comment .= ' ' . $tokens[$i]['content']; + $commentLines[] = [ + 'comment' => $tokens[$i]['content'], + 'token' => $i, + 'indent' => $indent, + ]; + } + } + } else { + $error = 'Missing parameter comment'; + $phpcsFile->addError($error, $tag, 'MissingParamComment'); + $commentLines[] = ['comment' => '']; + } + } else { + $error = 'Missing parameter name'; + $phpcsFile->addError($error, $tag, 'MissingParamName'); + } + } else { + $error = 'Missing parameter type'; + $phpcsFile->addError($error, $tag, 'MissingParamType'); + } + + $params[] = [ + 'tag' => $tag, + 'type' => $type, + 'var' => $var, + 'comment' => $comment, + 'commentLines' => $commentLines, + 'type_space' => $typeSpace, + 'var_space' => $varSpace, + ]; + } + + $realParams = $phpcsFile->getMethodParameters($stackPtr); + $foundParams = []; + + // We want to use ... for all variable length arguments, so added + // this prefix to the variable name so comparisons are easier. + foreach ($realParams as $pos => $param) { + if ($param['variable_length'] === true) { + $realParams[$pos]['name'] = '...' . $realParams[$pos]['name']; + } + } + + foreach ($params as $pos => $param) { + // If the type is empty, the whole line is empty. + if ($param['type'] === '') { + continue; + } + + // Check the param type value. + $typeNames = explode('|', $param['type']); + foreach ($typeNames as $typeName) { + $suggestedName = CodingStandard::suggestType($typeName); + if ($typeName !== $suggestedName) { + $error = 'Expected "%s" but found "%s" for parameter type'; + $data = [ + $suggestedName, + $typeName, + ]; + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'IncorrectParamVarName', $data); + + if ($fix) { + $content = $suggestedName; + $content .= str_repeat(' ', $param['type_space']); + $content .= $param['var']; + $content .= str_repeat(' ', $param['var_space']); + if (isset($param['commentLines'][0])) { + $content .= $param['commentLines'][0]['comment']; + } + + $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + } + } elseif (count($typeNames) === 1) { + // Check type hint for array and custom type. + $suggestedTypeHint = ''; + if (strpos($suggestedName, 'array') !== false || substr($suggestedName, -2) === '[]') { + $suggestedTypeHint = 'array'; + } elseif (strpos($suggestedName, 'callable') !== false) { + $suggestedTypeHint = 'callable'; + } elseif (strpos($suggestedName, 'callback') !== false) { + $suggestedTypeHint = 'callable'; + } elseif (! in_array($typeName, CodingStandard::$allowedTypes)) { + $suggestedTypeHint = $suggestedName; + } elseif ($this->phpVersion >= 70000) { + if ($typeName === 'string') { + $suggestedTypeHint = 'string'; + } elseif ($typeName === 'int' || $typeName === 'integer') { + $suggestedTypeHint = 'int'; + } elseif ($typeName === 'float') { + $suggestedTypeHint = 'float'; + } elseif ($typeName === 'bool' || $typeName === 'boolean') { + $suggestedTypeHint = 'bool'; + } + } + + if ($suggestedTypeHint !== '' && isset($realParams[$pos])) { + $typeHint = $realParams[$pos]['type_hint']; + if ($typeHint === '') { + $error = 'Type hint "%s" missing for %s'; + $data = [ + $suggestedTypeHint, + $param['var'], + ]; + + $errorCode = 'TypeHintMissing'; + if ($suggestedTypeHint === 'string' + || $suggestedTypeHint === 'int' + || $suggestedTypeHint === 'float' + || $suggestedTypeHint === 'bool' + ) { + $errorCode = 'Scalar' . $errorCode; + } + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } elseif ($typeHint !== substr($suggestedTypeHint, (strlen($typeHint) * -1))) { + $error = 'Expected type hint "%s"; found "%s" for %s'; + $data = [ + $suggestedTypeHint, + $typeHint, + $param['var'], + ]; + $phpcsFile->addError($error, $stackPtr, 'IncorrectTypeHint', $data); + }//end if + } elseif ($suggestedTypeHint === '' && isset($realParams[$pos])) { + $typeHint = $realParams[$pos]['type_hint']; + if ($typeHint !== '') { + $error = 'Unknown type hint "%s" found for %s'; + $data = [ + $typeHint, + $param['var'], + ]; + $phpcsFile->addError($error, $stackPtr, 'InvalidTypeHint', $data); + } + } + } + } + + if ($param['var'] === '') { + continue; + } + + $foundParams[] = $param['var']; + + // Check number of spaces after the type. + $spaces = ($maxType - strlen($param['type']) + 1); + if ($param['type_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter type; %s found'; + $data = [ + $spaces, + $param['type_space'], + ]; + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + + $content = $param['type']; + $content .= str_repeat(' ', $spaces); + $content .= $param['var']; + $content .= str_repeat(' ', $param['var_space']); + $content .= $param['commentLines'][0]['comment']; + $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + + // Fix up the indent of additional comment lines. + foreach ($param['commentLines'] as $lineNum => $line) { + if ($lineNum === 0 + || $param['commentLines'][$lineNum]['indent'] === 0 + ) { + continue; + } + + $newIndent = ($param['commentLines'][$lineNum]['indent'] + $spaces - $param['type_space']); + $phpcsFile->fixer->replaceToken( + ($param['commentLines'][$lineNum]['token'] - 1), + str_repeat(' ', $newIndent) + ); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // Make sure the param name is correct. + if (isset($realParams[$pos])) { + $realName = $realParams[$pos]['name']; + if ($realName !== $param['var']) { + $code = 'ParamNameNoMatch'; + $data = [ + $param['var'], + $realName, + ]; + + $error = 'Doc comment for parameter %s does not match '; + if (strtolower($param['var']) === strtolower($realName)) { + $error .= 'case of '; + $code = 'ParamNameNoCaseMatch'; + } + + $error .= 'actual variable name %s'; + + $phpcsFile->addError($error, $param['tag'], $code, $data); + } + } elseif (substr($param['var'], -4) !== ',...') { + // We must have an extra parameter comment. + $error = 'Superfluous parameter comment'; + $phpcsFile->addError($error, $param['tag'], 'ExtraParamComment'); + } + + if ($param['comment'] === '') { + continue; + } + + // Check number of spaces after the var name. + $spaces = ($maxVar - strlen($param['var']) + 1); + if ($param['var_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter name; %s found'; + $data = [ + $spaces, + $param['var_space'], + ]; + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + + $content = $param['type']; + $content .= str_repeat(' ', $param['type_space']); + $content .= $param['var']; + $content .= str_repeat(' ', $spaces); + $content .= $param['commentLines'][0]['comment']; + $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + + // Fix up the indent of additional comment lines. + foreach ($param['commentLines'] as $lineNum => $line) { + if ($lineNum === 0 + || $param['commentLines'][$lineNum]['indent'] === 0 + ) { + continue; + } + + $newIndent = ($param['commentLines'][$lineNum]['indent'] + $spaces - $param['var_space']); + $phpcsFile->fixer->replaceToken( + ($param['commentLines'][$lineNum]['token'] - 1), + str_repeat(' ', $newIndent) + ); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // Param comments must start with a capital letter and end with the full stop. + if (preg_match('/^(\p{Ll}|\P{L})/u', $param['comment']) === 1) { + $error = 'Parameter comment must start with a capital letter'; + $phpcsFile->addError($error, $param['tag'], 'ParamCommentNotCapital'); + } + + $lastChar = substr($param['comment'], -1); + if ($lastChar !== '.') { + $error = 'Parameter comment must end with a full stop'; + $phpcsFile->addError($error, $param['tag'], 'ParamCommentFullStop'); + } + } + + $realNames = []; + foreach ($realParams as $realParam) { + $realNames[] = $realParam['name']; + } + + // Report missing comments. + $diff = array_diff($realNames, $foundParams); + foreach ($diff as $neededParam) { + $error = 'Doc comment for parameter "%s" missing'; + $data = [$neededParam]; + $phpcsFile->addError($error, $commentStart, 'MissingParamTag', $data); + } + } +} diff --git a/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php b/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php new file mode 100644 index 00000000..912098c4 --- /dev/null +++ b/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php @@ -0,0 +1,160 @@ + + * @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 + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class VariableCommentSniff extends PHP_CodeSniffer_Standards_AbstractVariableSniff +{ + /** + * Called to process class member vars. + * + * @param PHP_CodeSniffer_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 processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $ignore = [ + T_PUBLIC, + T_PRIVATE, + T_PROTECTED, + T_VAR, + T_STATIC, + T_WHITESPACE, + ]; + + $commentEnd = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + if ($commentEnd === false + || ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG + && $tokens[$commentEnd]['code'] !== T_COMMENT) + ) { + $phpcsFile->addError('Missing member variable doc comment', $stackPtr, 'Missing'); + return; + } + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $phpcsFile->addError( + 'You must use "/**" style comments for a member variable comment', + $stackPtr, + 'WrongStyle' + ); + + return; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + + $foundVar = null; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@var') { + if ($foundVar !== null) { + $error = 'Only one @var tag is allowed in a member variable comment'; + $phpcsFile->addError($error, $tag, 'DuplicateVar'); + } else { + $foundVar = $tag; + } + } elseif ($tokens[$tag]['content'] === '@see') { + // Make sure the tag isn't empty. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for @see tag in member variable comment'; + $phpcsFile->addError($error, $tag, 'EmptySees'); + } + } else { + $error = '%s tag is not allowed in member variable comment'; + $data = [$tokens[$tag]['content']]; + $phpcsFile->addWarning($error, $tag, 'TagNotAllowed', $data); + } + } + + // The @var tag is the only one we require. + if ($foundVar === null) { + $error = 'Missing @var tag in member variable comment'; + $phpcsFile->addError($error, $commentEnd, 'MissingVar'); + return; + } + + $firstTag = $tokens[$commentStart]['comment_tags'][0]; + if ($foundVar !== null && $tokens[$firstTag]['content'] !== '@var') { + $error = 'The @var tag must be the first tag in a member variable comment'; + $phpcsFile->addError($error, $foundVar, 'VarOrder'); + } + + // Make sure the tag isn't empty and has the correct padding. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $foundVar, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$foundVar]['line']) { + $error = 'Content missing for @var tag in member variable comment'; + $phpcsFile->addError($error, $foundVar, 'EmptyVar'); + return; + } + + $varType = $tokens[($foundVar + 2)]['content']; + // changed to use bool and int instead of boolean and integer accordingly + $suggestedType = CodingStandard::suggestType($varType); + if ($varType !== $suggestedType) { + $error = 'Expected "%s" but found "%s" for @var tag in member variable comment'; + $data = [ + $suggestedType, + $varType, + ]; + $fix = $phpcsFile->addFixableError($error, ($foundVar + 2), 'IncorrectVarType', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken(($foundVar + 2), $suggestedType); + } + } + } + + /** + * Called to process a normal variable. + * + * Not required for this sniff. + * + * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param int $stackPtr The position where the double quoted + * string was found. + * + * @return void + */ + protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + } + + /** + * Called to process variables found in double quoted strings. + * + * Not required for this sniff. + * + * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param int $stackPtr The position where the double quoted + * string was found. + * + * @return void + */ + protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + } +} diff --git a/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php b/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php new file mode 100644 index 00000000..d5ec5f05 --- /dev/null +++ b/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php @@ -0,0 +1,68 @@ +getTokens(); + + $prev = $phpcsFile->findPrevious( + array_merge(\PHP_CodeSniffer_Tokens::$methodPrefixes, [T_WHITESPACE]), + $stackPtr - 1, + null, + true + ); + + $visibility = $phpcsFile->findPrevious( + [T_PUBLIC, T_PROTECTED, T_PRIVATE], + $stackPtr - 1, + $prev + ); + + // Skip methods without visibility. + if (! $visibility) { + return; + } + + // Skip methods without body. + if (! isset($tokens[$stackPtr]['scope_closer'])) { + return; + } + + $scopeCloser = $tokens[$stackPtr]['scope_closer']; + + $contentAfter = $phpcsFile->findNext(T_WHITESPACE, $scopeCloser + 1, null, true); + if ($contentAfter !== false + && $tokens[$contentAfter]['line'] - $tokens[$scopeCloser]['line'] !== 2 + && $tokens[$contentAfter]['code'] !== T_CLOSE_CURLY_BRACKET + ) { + $error = 'Expected 1 blank line after method; %d found'; + $found = max($tokens[$contentAfter]['line'] - $tokens[$scopeCloser]['line'] - 1, 0); + $fix = $phpcsFile->addFixableError($error, $scopeCloser, '', [$found]); + + if ($fix) { + if ($found) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $scopeCloser + 1; $i < $contentAfter - 1; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->addNewline($scopeCloser); + } + } + } + } +} diff --git a/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php b/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php new file mode 100644 index 00000000..8cb4dbec --- /dev/null +++ b/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -0,0 +1,73 @@ +getTokens(); + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + + // If it's a php reserved var, then its ok. + if (in_array($varName, $this->phpReservedVars, true)) { + return; + } + + $objOperator = $phpcsFile->findPrevious([T_WHITESPACE], ($stackPtr - 1), null, true); + if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON) { + return; // skip MyClass::$variable, there might be no control over the declaration + } + + if (! PHP_CodeSniffer::isCamelCaps($varName, false, true, false)) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, self::CODE_CAMEL_CAPS, $data); + } + } + + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr Position of the double quoted string. + */ + protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + // handled by PSR2.Classes.PropertyDeclaration + } + + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr Position of the double quoted string. + */ + protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + // handled by Squiz.Strings.DoubleQuoteUsage + } +} diff --git a/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php new file mode 100644 index 00000000..0afdcdb7 --- /dev/null +++ b/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -0,0 +1,117 @@ +getTokens(); + + // Process !! casts + if ($tokens[$stackPtr]['code'] == T_BOOLEAN_NOT) { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if (! $nextToken) { + return; + } + if ($tokens[$nextToken]['code'] != T_BOOLEAN_NOT) { + return; + } + $error = 'Usage of !! cast is not allowed. Please use (bool) to cast.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($stackPtr, '(bool)'); + $phpcsFile->fixer->replaceToken($nextToken, ''); + $phpcsFile->fixer->endChangeset(); + } + + return; + } + + // Only allow short forms if both short and long forms are possible + $matching = [ + '(boolean)' => '(bool)', + '(integer)' => '(int)', + ]; + $content = $tokens[$stackPtr]['content']; + $key = strtolower($content); + if (isset($matching[$key])) { + $error = 'Please use %s instead of %s.'; + $data = [ + $matching[$key], + $content, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($stackPtr, $matching[$key]); + } + + return; + } + + if ($content !== $key) { + $error = 'Please use %s instead of %s.'; + $data = [ + $key, + $content, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($stackPtr, $key); + } + } + } +} diff --git a/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php new file mode 100644 index 00000000..dca15b1e --- /dev/null +++ b/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -0,0 +1,120 @@ +getTokens(); + + $prevToken = $tokens[$stackPtr - 1]; + $prevType = $prevToken['code']; + if (isset(PHP_CodeSniffer_Tokens::$emptyTokens[$prevType])) { + $nonSpace = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr - 2, null, true); + $expected = $tokens[$nonSpace]['content'] . ','; + $found = $phpcsFile->getTokensAsString($nonSpace, ($stackPtr - $nonSpace)) . ','; + $error = 'Space found before comma; expected "%s" but found "%s"'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeComma', $data); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $stackPtr - 1; $i > $nonSpace; $i--) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + $nextToken = $tokens[$stackPtr + 1]; + $nextType = $nextToken['code']; + + // There is no space after comma. + if ($nextType !== T_WHITESPACE) { + $error = 'Expected 1 space after comma; found 0'; + $fix = $phpcsFile->addFixableError($error, $stackPtr + 1, 'NoSpaceAfterComma'); + if ($fix) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } elseif (strlen($nextToken['content']) !== 1) { + // There is more than one space after comma. + + // Check if this is not before a comment at the end of the line + if ($tokens[$stackPtr + 2]['code'] !== T_COMMENT + && $tokens[$stackPtr + 3]['code'] !== T_WHITESPACE + && $tokens[$stackPtr + 3]['content'] !== "\n" + ) { + if ($tokens[$stackPtr + 2]['code'] === T_DOC_COMMENT_OPEN_TAG) { + $phpcsFile->addError( + 'Doc comment is not allowed here. Please use normal comment: /* ... */ or // ...', + $stackPtr + 2, + 'DocCommentNotAllowed' + ); + } else { + $openArray = $phpcsFile->findPrevious([T_OPEN_SHORT_ARRAY], $stackPtr); + $beforeOpening = $phpcsFile->findPrevious( + PHP_CodeSniffer_Tokens::$emptyTokens, + $openArray - 1, + null, + true + ); + $closeArray = $phpcsFile->findNext([T_CLOSE_SHORT_ARRAY], $stackPtr); + $afterClosing = $phpcsFile->findNext( + array_merge(PHP_CodeSniffer_Tokens::$emptyTokens, [T_COMMA]), + $closeArray + 1, + null, + true + ); + + if ($tokens[$openArray]['line'] !== $tokens[$closeArray]['line'] + || $tokens[$beforeOpening]['line'] === $tokens[$openArray]['line'] + || $tokens[$afterClosing]['line'] === $tokens[$closeArray]['line'] + ) { + $error = 'Expected 1 space after comma; found %d'; + $data = [ + strlen($nextToken['content']), + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr + 1, 'SpacingAfterComma', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($stackPtr + 1, ' '); + } + } + } + } + } + } +} diff --git a/ZendCodingStandard/ruleset.xml b/ZendCodingStandard/ruleset.xml new file mode 100644 index 00000000..a1fa7b98 --- /dev/null +++ b/ZendCodingStandard/ruleset.xml @@ -0,0 +1,75 @@ + + + Zend Framework Coding Standard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Variable "%s" not allowed in double quoted string; use sprintf() instead. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/composer.json b/composer.json index 89f82020..361d9df7 100644 --- a/composer.json +++ b/composer.json @@ -7,6 +7,16 @@ "coding standard" ], "require": { - "squizlabs/php_codesniffer": "^2.7" + "squizlabs/php_codesniffer": "^2.7", + "slevomat/coding-standard": "^1.1" + }, + "autoload": { + "psr-4": { + "ZendCodingStandard\\": "ZendCodingStandard" + } + }, + "scripts": { + "cs-check": "phpcs", + "cs-fix": "phpcbf" } } diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 00000000..549bc6ec --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,6 @@ + + + + + ZendCodingStandard + diff --git a/ruleset.xml b/ruleset.xml index 2e2536e0..174cd238 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -1,23 +1,4 @@ - Zend Framework Coding Standard - - - - - - - - - - - - - - - - - - - + From c55adc250a0ec34ef9d236be288fb6842824c6ef Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 14 Nov 2016 22:43:49 +0000 Subject: [PATCH 002/225] Removed redundant brackets --- .../Sniffs/Commenting/FunctionCommentSniff.php | 18 +++++++++--------- .../Sniffs/Commenting/VariableCommentSniff.php | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index cf7b078c..9a1adfd4 100644 --- a/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -70,8 +70,8 @@ protected function processReturn(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co } if ($return !== null) { - $content = $tokens[($return + 2)]['content']; - if (empty($content) || $tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) { + $content = $tokens[$return + 2]['content']; + if (empty($content) || $tokens[$return + 2]['code'] !== T_DOC_COMMENT_STRING) { $error = 'Return type missing for @return tag in function comment'; $phpcsFile->addError($error, $return, 'MissingReturnType'); } else { @@ -185,9 +185,9 @@ protected function processThrows(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co $exception = null; $comment = null; - if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + if ($tokens[$tag + 2]['code'] === T_DOC_COMMENT_STRING) { $matches = []; - preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[($tag + 2)]['content'], $matches); + preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[$tag + 2]['content'], $matches); $exception = $matches[1]; if (isset($matches[2]) && trim($matches[2]) !== '') { $comment = $matches[2]; @@ -265,11 +265,11 @@ protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co $varSpace = 0; $comment = ''; $commentLines = []; - if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + if ($tokens[$tag + 2]['code'] === T_DOC_COMMENT_STRING) { $matches = []; preg_match( '/([^$&.]+)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', - $tokens[($tag + 2)]['content'], + $tokens[$tag + 2]['content'], $matches ); @@ -300,8 +300,8 @@ protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co ]; // Any strings until the next tag belong to this comment. - if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)])) { - $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; + if (isset($tokens[$commentStart]['comment_tags'][$pos + 1])) { + $end = $tokens[$commentStart]['comment_tags'][$pos + 1]; } else { $end = $tokens[$commentStart]['comment_closer']; } @@ -310,7 +310,7 @@ protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { $indent = 0; if ($tokens[$i - 1]['code'] === T_DOC_COMMENT_WHITESPACE) { - $indent = strlen($tokens[($i - 1)]['content']); + $indent = strlen($tokens[$i - 1]['content']); } $comment .= ' ' . $tokens[$i]['content']; diff --git a/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php b/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php index 912098c4..03312017 100644 --- a/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php +++ b/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php @@ -111,7 +111,7 @@ public function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr) return; } - $varType = $tokens[($foundVar + 2)]['content']; + $varType = $tokens[$foundVar + 2]['content']; // changed to use bool and int instead of boolean and integer accordingly $suggestedType = CodingStandard::suggestType($varType); if ($varType !== $suggestedType) { From 4528d1ec95c3a42fd66502e34b72851056b8da5f Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 14 Nov 2016 22:45:12 +0000 Subject: [PATCH 003/225] Fix suggested type for arrays - array(type1 => type2) --- ZendCodingStandard/CodingStandard.php | 31 ++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/ZendCodingStandard/CodingStandard.php b/ZendCodingStandard/CodingStandard.php index 23f88646..fb6a788c 100644 --- a/ZendCodingStandard/CodingStandard.php +++ b/ZendCodingStandard/CodingStandard.php @@ -17,7 +17,8 @@ class CodingStandard public static function suggestType($varType) { - switch (strtolower($varType)) { + $lowerVarType = strtolower($varType); + switch ($lowerVarType) { case 'bool': case 'boolean': return 'bool'; @@ -30,6 +31,34 @@ public static function suggestType($varType) return 'bool[]'; } + if (strpos($lowerVarType, 'array(') !== false) { + // Valid array declaration: + // array, array(type), array(type1 => type2). + $matches = []; + $pattern = '/^array\(\s*([^\s^=^>]*)(\s*=>\s*(.*))?\s*\)/i'; + if (preg_match($pattern, $varType, $matches) !== 0) { + $type1 = ''; + if (isset($matches[1]) === true) { + $type1 = $matches[1]; + } + + $type2 = ''; + if (isset($matches[3]) === true) { + $type2 = $matches[3]; + } + + $type1 = self::suggestType($type1); + $type2 = self::suggestType($type2); + if ($type2 !== '') { + $type2 = ' => ' . $type2; + } + + return sprintf('array(%s%s)', $type1, $type2); + } + + return 'array'; + } + return \PHP_CodeSniffer::suggestType($varType); } } From 3ba6ca7b5b3631be722b2c7841b8f734f96078da Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 14 Nov 2016 22:48:40 +0000 Subject: [PATCH 004/225] Package configuration - added PHPUnit configuration - added Travis configuration - added Coveralls configuration - updated phpcs.xml to exclude .inc test files - updated .gitignore - added composer.lock - added .gitattributes - added abstract TestCase for Sniff tests --- .coveralls.yml | 2 + .gitattributes | 7 + .gitignore | 4 +- .travis.yml | 78 ++ ZendCodingStandard/Tests/TestCase.php | 333 ++++++ composer.json | 19 +- composer.lock | 1485 +++++++++++++++++++++++++ phpcs.xml | 2 + phpunit.xml.dist | 16 + 9 files changed, 1943 insertions(+), 3 deletions(-) create mode 100644 .coveralls.yml create mode 100644 .gitattributes create mode 100644 .travis.yml create mode 100644 ZendCodingStandard/Tests/TestCase.php create mode 100644 composer.lock create mode 100644 phpunit.xml.dist diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 00000000..bc71b62f --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1,2 @@ +coverage_clover: clover.xml +json_path: coveralls-upload.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..4914e2e1 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +/ZendCodingStandard/Tests export-ignore +.coveralls.yml +.gitattributes export-ignore +.gitignore export-ignore +.travis.yml export-ignore +phpcs.xml export-ignore +phpunit.xml.dist export-ignore diff --git a/.gitignore b/.gitignore index d1502b08..ac54a172 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ vendor/ -composer.lock +phpunit.xml +clover.xml +coveralls-upload.json diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..176c1a22 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,78 @@ +sudo: false + +language: php + +cache: + directories: + - $HOME/.composer/cache + - vendor + +env: + global: + - COMPOSER_ARGS="--no-interaction" + - COVERAGE_DEPS="satooshi/php-coveralls" + +matrix: + include: + - php: 5.6 + env: + - DEPS=lowest + - php: 5.6 + env: + - DEPS=locked + - TEST_COVERAGE=true + - php: 5.6 + env: + - DEPS=latest + - php: 7 + env: + - DEPS=lowest + - php: 7 + env: + - DEPS=locked + - CS_CHECK=true + - php: 7 + env: + - DEPS=latest + - php: 7.1 + env: + - DEPS=lowest + - php: 7.1 + env: + - DEPS=locked + - php: 7.1 + env: + - DEPS=latest + - php: hhvm + env: + - DEPS=lowest + - php: hhvm + env: + - DEPS=locked + - php: hhvm + env: + - DEPS=latest + allow_failures: + - php: hhvm + +notifications: + irc: "irc.freenode.org#zftalk.dev" + email: false + +before_install: + - if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi + - travis_retry composer self-update + +install: + - if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $COVERAGE_DEPS ; fi + - if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi + - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-lowest --prefer-stable $COMPOSER_ARGS ; fi + - travis_retry composer install $COMPOSER_ARGS + - composer show + +script: + - if [[ $TEST_COVERAGE == 'true' ]]; then composer test-coverage ; else composer test ; fi + - if [[ $CS_CHECK == 'true' ]]; then composer cs-check ; fi + +after_script: + - if [[ $TEST_COVERAGE == 'true' ]]; then composer upload-coverage ; fi diff --git a/ZendCodingStandard/Tests/TestCase.php b/ZendCodingStandard/Tests/TestCase.php new file mode 100644 index 00000000..64275619 --- /dev/null +++ b/ZendCodingStandard/Tests/TestCase.php @@ -0,0 +1,333 @@ +phpcs = new PHP_CodeSniffer(); + } + + protected function getTestFiles($testFileBase) + { + $testFiles = []; + + $dir = substr($testFileBase, 0, strrpos($testFileBase, DIRECTORY_SEPARATOR)); + $di = new \DirectoryIterator($dir); + + foreach ($di as $file) { + if (! $file->isFile()) { + continue; + } + + $path = $file->getPathname(); + // if (substr($path, 9, strlen($testFileBase)) === $testFileBase) + if ($path !== $testFileBase . 'php' && substr($path, -5) !== 'fixed') { + $testFiles[] = $path; + } + } + + sort($testFiles); + + return $testFiles; + } + + final public function testSniff() + { + $basename = substr(get_class($this), 0, -8); + + $standardName = substr($basename, 0, strpos($basename, '\\')); + + $parts = explode('\\', $basename); + $sniffCode = $parts[0] . '.' . $parts[2] . '.' . $parts[3]; + + $testFileBase = __DIR__ + . '/../../' + . str_replace('\\', DIRECTORY_SEPARATOR, $basename) . 'UnitTest.'; + + $testFiles = $this->getTestFiles($testFileBase); + + $this->phpcs->initStandard($standardName, [$sniffCode]); + $this->phpcs->setIgnorePatterns([]); + + $failureMessages = []; + foreach ($testFiles as $testFile) { + $filename = basename($testFile); + + try { + $phpcsFile = $this->phpcs->processFile($testFile); + } catch (\Exception $e) { + $this->fail(sprintf( + 'An unexpected exception has been caught: %s', + $e->getMessage() + )); + } + + + $failures = $this->generateFailureMessages($phpcsFile); + $failureMessages = array_merge($failureMessages, $failures); + + if ($phpcsFile->getFixableCount() > 0) { + // Attempt to fix the errors. + $phpcsFile->fixer->fixFile(); + $fixable = $phpcsFile->getFixableCount(); + if ($fixable) { + $failureMessages[] = sprintf( + 'Failed to fix %d fixable violations in %s', + $fixable, + $filename + ); + } + + // Check for a .fixed file to check for accuracy of fixes. + $fixedFile = $testFile . '.fixed'; + if (file_exists($fixedFile)) { + $diff = $phpcsFile->fixer->generateDiff($fixedFile); + if (trim($diff) !== '') { + $filename = basename($testFile); + $fixedFilename = basename($fixedFile); + $failureMessages[] = sprintf( + 'Fixed version of %s does not match expected version in %s; the diff is' . PHP_EOL . '%s', + $filename, + $fixedFilename, + $diff + ); + } + } + } + } + + if (! empty($failureMessages)) { + $this->fail(implode(PHP_EOL, $failureMessages)); + } + } + + public function generateFailureMessages(PHP_CodeSniffer_File $file) + { + $testFile = $file->getFilename(); + + $foundErrors = $file->getErrors(); + $foundWarnings = $file->getWarnings(); + $expectedErrors = $this->getErrorList(basename($testFile)); + $expectedWarnings = $this->getWarningList(basename($testFile)); + + if (! is_array($expectedErrors)) { + throw new PHP_CodeSniffer_Exception('getErrorList() must return an array'); + } + + if (! is_array($expectedWarnings)) { + throw new PHP_CodeSniffer_Exception('getWarningList() must return an array'); + } + + /* + We merge errors and warnings together to make it easier + to iterate over them and produce the errors string. In this way, + we can report on errors and warnings in the same line even though + it's not really structured to allow that. + */ + + $allProblems = []; + $failureMessages = []; + + foreach ($foundErrors as $line => $lineErrors) { + foreach ($lineErrors as $column => $errors) { + if (! isset($allProblems[$line])) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $foundErrorsTemp = []; + foreach ($allProblems[$line]['found_errors'] as $foundError) { + $foundErrorsTemp[] = $foundError; + } + + $errorsTemp = []; + foreach ($errors as $foundError) { + $errorsTemp[] = $foundError['message'] . ' (' . $foundError['source'] . ')'; + + $source = $foundError['source']; + if (! in_array($source, $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'])) { + $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'][] = $source; + } + + if ($foundError['fixable'] === true + && ! in_array($source, $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES']) + ) { + $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'][] = $source; + } + } + + $allProblems[$line]['found_errors'] = array_merge($foundErrorsTemp, $errorsTemp); + } + + if (isset($expectedErrors[$line])) { + $allProblems[$line]['expected_errors'] = $expectedErrors[$line]; + } else { + $allProblems[$line]['expected_errors'] = 0; + } + + unset($expectedErrors[$line]); + } + + foreach ($expectedErrors as $line => $numErrors) { + if (! isset($allProblems[$line])) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $allProblems[$line]['expected_errors'] = $numErrors; + } + + foreach ($foundWarnings as $line => $lineWarnings) { + foreach ($lineWarnings as $column => $warnings) { + if (! isset($allProblems[$line])) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $foundWarningsTemp = []; + foreach ($allProblems[$line]['found_warnings'] as $foundWarning) { + $foundWarningsTemp[] = $foundWarning; + } + + $warningsTemp = []; + foreach ($warnings as $warning) { + $warningsTemp[] = $warning['message'] . ' (' . $warning['source'] . ')'; + } + + $allProblems[$line]['found_warnings'] = array_merge($foundWarningsTemp, $warningsTemp); + } + + if (isset($expectedWarnings[$line])) { + $allProblems[$line]['expected_warnings'] = $expectedWarnings[$line]; + } else { + $allProblems[$line]['expected_warnings'] = 0; + } + + unset($expectedWarnings[$line]); + } + + foreach ($expectedWarnings as $line => $numWarnings) { + if (! isset($allProblems[$line])) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $allProblems[$line]['expected_warnings'] = $numWarnings; + } + + // Order the messages by line number. + ksort($allProblems); + + foreach ($allProblems as $line => $problems) { + $numErrors = count($problems['found_errors']); + $numWarnings = count($problems['found_warnings']); + $expectedErrors = $problems['expected_errors']; + $expectedWarnings = $problems['expected_warnings']; + + $errors = ''; + $foundString = ''; + + if ($expectedErrors !== $numErrors || $expectedWarnings !== $numWarnings) { + $lineMessage = sprintf('[LINE %s]', $line); + $expectedMessage = 'Expected '; + $foundMessage = sprintf('in %s but found ', basename($testFile)); + + if ($expectedErrors !== $numErrors) { + $expectedMessage .= sprintf('%s error(s)', $expectedErrors); + $foundMessage .= sprintf('%s error(s)', $numErrors); + if ($numErrors !== 0) { + $foundString .= 'error(s)'; + $errors .= implode(PHP_EOL . ' -> ', $problems['found_errors']); + } + + if ($expectedWarnings !== $numWarnings) { + $expectedMessage .= ' and '; + $foundMessage .= ' and '; + if ($numWarnings !== 0) { + if ($foundString !== '') { + $foundString .= ' and '; + } + } + } + } + + if ($expectedWarnings !== $numWarnings) { + $expectedMessage .= sprintf('%s warning(s)', $expectedWarnings); + $foundMessage .= sprintf('%s warning(s)', $numWarnings); + if ($numWarnings !== 0) { + $foundString .= 'warning(s)'; + if (! empty($errors)) { + $errors .= PHP_EOL . ' -> '; + } + + $errors .= implode(PHP_EOL . ' -> ', $problems['found_warnings']); + } + } + + $fullMessage = sprintf('%s %s %s.', $lineMessage, $expectedMessage, $foundMessage); + if ($errors !== '') { + $fullMessage .= sprintf(' The %s found were:' . PHP_EOL . ' -> %s', $foundString, $errors); + } + + $failureMessages[] = $fullMessage; + } + } + + return $failureMessages; + } + + /** + * 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(int => int) + */ + abstract protected function 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(int => int) + */ + abstract protected function getWarningList(); +} diff --git a/composer.json b/composer.json index 361d9df7..b51b871f 100644 --- a/composer.json +++ b/composer.json @@ -10,13 +10,28 @@ "squizlabs/php_codesniffer": "^2.7", "slevomat/coding-standard": "^1.1" }, + "require-dev": { + "phpunit/phpunit": "^5.6" + }, "autoload": { "psr-4": { - "ZendCodingStandard\\": "ZendCodingStandard" + "ZendCodingStandard\\Sniffs\\": "ZendCodingStandard/Sniffs" + } + }, + "autoload-dev": { + "psr-4": { + "ZendCodingStandard\\Tests\\": "ZendCodingStandard/Tests" } }, "scripts": { + "check": [ + "@cs-check", + "@test" + ], + "upload-coverage": "coveralls -v", "cs-check": "phpcs", - "cs-fix": "phpcbf" + "cs-fix": "phpcbf", + "test": "phpunit", + "test-coverage": "phpunit --coverage-clover clover.xml" } } diff --git a/composer.lock b/composer.lock new file mode 100644 index 00000000..093fac00 --- /dev/null +++ b/composer.lock @@ -0,0 +1,1485 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "24a044053a919e5b2a7acd6f6918468f", + "content-hash": "129ed88cc335edde3c6340c9d15b96ac", + "packages": [ + { + "name": "jakub-onderka/php-parallel-lint", + "version": "v0.9.2", + "source": { + "type": "git", + "url": "https://github.com/JakubOnderka/PHP-Parallel-Lint.git", + "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Parallel-Lint/zipball/2ead2e4043ab125bee9554f356e0a86742c2d4fa", + "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "jakub-onderka/php-console-highlighter": "~0.3", + "nette/tester": "~1.3" + }, + "suggest": { + "jakub-onderka/php-console-highlighter": "Highlight syntax in code snippet" + }, + "bin": [ + "parallel-lint" + ], + "type": "library", + "autoload": { + "classmap": [ + "./" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "jakub.onderka@gmail.com" + } + ], + "description": "This tool check syntax of PHP files about 20x faster than serial check.", + "homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint", + "time": "2015-12-15 10:42:16" + }, + { + "name": "slevomat/coding-standard", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/slevomat/coding-standard.git", + "reference": "53c24d3fa620dadc832b6d297f11d908835af97f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/53c24d3fa620dadc832b6d297f11d908835af97f", + "reference": "53c24d3fa620dadc832b6d297f11d908835af97f", + "shasum": "" + }, + "require": { + "jakub-onderka/php-parallel-lint": "^0.9.2", + "php": "^5.6|^7.0", + "squizlabs/php_codesniffer": "^2.6.0" + }, + "require-dev": { + "consistence/coding-standard": "^0.11.0", + "phing/phing": "^2.9", + "phpstan/phpstan": "0.1", + "phpunit/phpunit": "^5.0", + "satooshi/php-coveralls": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "SlevomatCodingStandard\\": "SlevomatCodingStandard" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Slevomat Coding Standard for PHP_CodeSniffer extends Consistence Coding Standard by providing sniffs with additional checks.", + "time": "2016-08-10 15:35:53" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "2.7.0", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", + "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "bin": [ + "scripts/phpcs", + "scripts/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "classmap": [ + "CodeSniffer.php", + "CodeSniffer/CLI.php", + "CodeSniffer/Exception.php", + "CodeSniffer/File.php", + "CodeSniffer/Fixer.php", + "CodeSniffer/Report.php", + "CodeSniffer/Reporting.php", + "CodeSniffer/Sniff.php", + "CodeSniffer/Tokens.php", + "CodeSniffer/Reports/", + "CodeSniffer/Tokenizers/", + "CodeSniffer/DocGenerators/", + "CodeSniffer/Standards/AbstractPatternSniff.php", + "CodeSniffer/Standards/AbstractScopeSniff.php", + "CodeSniffer/Standards/AbstractVariableSniff.php", + "CodeSniffer/Standards/IncorrectPatternException.php", + "CodeSniffer/Standards/Generic/Sniffs/", + "CodeSniffer/Standards/MySource/Sniffs/", + "CodeSniffer/Standards/PEAR/Sniffs/", + "CodeSniffer/Standards/PSR1/Sniffs/", + "CodeSniffer/Standards/PSR2/Sniffs/", + "CodeSniffer/Standards/Squiz/Sniffs/", + "CodeSniffer/Standards/Zend/Sniffs/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "http://www.squizlabs.com/php-codesniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2016-09-01 23:53:02" + } + ], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14 21:17:01" + }, + { + "name": "myclabs/deep-copy", + "version": "1.5.5", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/399c1f9781e222f6eb6cc238796f5200d1b7f108", + "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "doctrine/collections": "1.*", + "phpunit/phpunit": "~4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "homepage": "https://github.com/myclabs/DeepCopy", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2016-10-31 17:19:45" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2015-12-27 11:43:31" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/type-resolver": "^0.2.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2016-09-30 07:12:33" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2016-06-10 07:14:17" + }, + { + "name": "phpspec/prophecy", + "version": "v1.6.1", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "58a8137754bc24b25740d4281399a4a3596058e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", + "reference": "58a8137754bc24b25740d4281399a4a3596058e0", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1", + "sebastian/recursion-context": "^1.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2016-06-07 08:13:47" + }, + { + "name": "phpunit/php-code-coverage", + "version": "4.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "6cba06ff75a1a63a71033e1a01b89056f3af1e8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6cba06ff75a1a63a71033e1a01b89056f3af1e8d", + "reference": "6cba06ff75a1a63a71033e1a01b89056f3af1e8d", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "^1.4.2", + "sebastian/code-unit-reverse-lookup": "~1.0", + "sebastian/environment": "^1.3.2 || ^2.0", + "sebastian/version": "~1.0|~2.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "^5.4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.4.0", + "ext-xmlwriter": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2016-11-01 05:06:24" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2015-06-21 13:08:43" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21 13:50:34" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4|~5" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2016-05-12 18:03:57" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.4.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2015-09-15 10:49:45" + }, + { + "name": "phpunit/phpunit", + "version": "5.6.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a9de0dbafeb6b1391b391fbb034734cb0af9f67c", + "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "~1.3", + "php": "^5.6 || ^7.0", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "^4.0.1", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "^3.2", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "^1.3 || ^2.0", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/object-enumerator": "~1.0", + "sebastian/resource-operations": "~1.0", + "sebastian/version": "~1.0|~2.0", + "symfony/yaml": "~2.1|~3.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-xdebug": "*", + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.6.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2016-11-14 06:39:40" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/238d7a2723bce689c79eeac9c7d5e1d623bb9dc2", + "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.6 || ^7.0", + "phpunit/php-text-template": "^1.2", + "sebastian/exporter": "^1.2" + }, + "conflict": { + "phpunit/phpunit": "<5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2016-10-09 07:01:45" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2016-02-13 06:45:14" + }, + { + "name": "sebastian/comparator", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2015-07-26 15:48:44" + }, + { + "name": "sebastian/diff", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-12-08 07:14:41" + }, + { + "name": "sebastian/environment", + "version": "1.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2016-08-18 05:49:44" + }, + { + "name": "sebastian/exporter", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2016-06-17 09:04:28" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12 03:26:01" + }, + { + "name": "sebastian/object-enumerator", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", + "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2016-01-28 13:25:10" + }, + { + "name": "sebastian/recursion-context", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "79860854756415e1cec8d186c9cf261cafd87dfc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/79860854756415e1cec8d186c9cf261cafd87dfc", + "reference": "79860854756415e1cec8d186c9cf261cafd87dfc", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2016-11-14 15:54:23" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28 20:34:47" + }, + { + "name": "sebastian/version", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", + "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-02-04 12:56:52" + }, + { + "name": "symfony/yaml", + "version": "v3.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/7ff51b06c6c3d5cc6686df69004a42c69df09e27", + "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2016-10-24 18:41:13" + }, + { + "name": "webmozart/assert", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "bb2d123231c095735130cc8f6d31385a44c7b308" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308", + "reference": "bb2d123231c095735130cc8f6d31385a44c7b308", + "shasum": "" + }, + "require": { + "php": "^5.3.3|^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2016-08-09 15:02:57" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/phpcs.xml b/phpcs.xml index 549bc6ec..a7e3a986 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -3,4 +3,6 @@ ZendCodingStandard + + */Tests/*.inc diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 00000000..e36b0911 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,16 @@ + + + + + ./ZendCodingStandard/Tests + + + + + ./ZendCodingStandard + + ./ZendCodingStandard/Tests + + + + From 34841a6528ce6b44cb2a4fb6fa7d96ec03a28776 Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 14 Nov 2016 22:49:06 +0000 Subject: [PATCH 005/225] Added tests for TrailingArrayComma sniff --- .../Arrays/TrailingArrayCommaUnitTest.inc | 23 +++++++++++++++++++ .../TrailingArrayCommaUnitTest.inc.fixed | 23 +++++++++++++++++++ .../Arrays/TrailingArrayCommaUnitTest.php | 22 ++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 ZendCodingStandard/Tests/Arrays/TrailingArrayCommaUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Arrays/TrailingArrayCommaUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Arrays/TrailingArrayCommaUnitTest.php diff --git a/ZendCodingStandard/Tests/Arrays/TrailingArrayCommaUnitTest.inc b/ZendCodingStandard/Tests/Arrays/TrailingArrayCommaUnitTest.inc new file mode 100644 index 00000000..eb8f17c6 --- /dev/null +++ b/ZendCodingStandard/Tests/Arrays/TrailingArrayCommaUnitTest.inc @@ -0,0 +1,23 @@ + 'bar' +]; +$a6 = [ + 'foo', 'bar', 'baz' +]; +$a7 = [ + ['a1'], + ['a2'], + ['a3'] +]; diff --git a/ZendCodingStandard/Tests/Arrays/TrailingArrayCommaUnitTest.inc.fixed b/ZendCodingStandard/Tests/Arrays/TrailingArrayCommaUnitTest.inc.fixed new file mode 100644 index 00000000..20480cb6 --- /dev/null +++ b/ZendCodingStandard/Tests/Arrays/TrailingArrayCommaUnitTest.inc.fixed @@ -0,0 +1,23 @@ + 'bar', +]; +$a6 = [ + 'foo', 'bar', 'baz', +]; +$a7 = [ + ['a1'], + ['a2'], + ['a3'], +]; diff --git a/ZendCodingStandard/Tests/Arrays/TrailingArrayCommaUnitTest.php b/ZendCodingStandard/Tests/Arrays/TrailingArrayCommaUnitTest.php new file mode 100644 index 00000000..25a9e96d --- /dev/null +++ b/ZendCodingStandard/Tests/Arrays/TrailingArrayCommaUnitTest.php @@ -0,0 +1,22 @@ + 1, + 14 => 1, + 17 => 1, + 22 => 1, + ]; + } + + public function getWarningList() + { + return []; + } +} From e895cbb4446041f3cf722112dbf9957908620127 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 15 Nov 2016 18:18:11 +0000 Subject: [PATCH 006/225] Use eolChar instead of "\n" --- .../Sniffs/Commenting/DocCommentSniff.php | 18 +++++++++--------- .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index 0543ad0b..3ec58070 100644 --- a/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -49,7 +49,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) return; } - if ($tokens[$commentEnd + 1]['content'] !== "\n") { + if ($tokens[$commentEnd + 1]['content'] !== $phpcsFile->eolChar) { $error = 'The close comment tag must be the only content on the line.'; $fix = $phpcsFile->addFixableError($error, $commentEnd); @@ -61,7 +61,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_WHITESPACE], $commentEnd - 1, null, true); - if ($tokens[$prev]['content'] !== "\n" + if ($tokens[$prev]['content'] !== $phpcsFile->eolChar && $tokens[$prev]['line'] === $tokens[$commentEnd]['line'] ) { $error = 'The close comment tag must be the only content on the line.'; @@ -72,11 +72,11 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } } - if ($tokens[$commentEnd + 2]['content'] === "\n") { + if ($tokens[$commentEnd + 2]['content'] === $phpcsFile->eolChar) { // There is empty line after doc block. $before = $tokens[$commentStart - 1]; - $indent = $before['code'] == T_OPEN_TAG || $before['content'] == "\n" + $indent = $before['code'] == T_OPEN_TAG || $before['content'] == $phpcsFile->eolChar ? 0 : strlen($before['content']); } elseif ($tokens[$commentEnd + 2]['code'] == T_WHITESPACE) { @@ -88,7 +88,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) // First line of the doc comment. $spaces = $tokens[$commentStart - 1]; if ($spaces['code'] === T_WHITESPACE - && $spaces['content'] !== "\n" + && $spaces['content'] !== $phpcsFile->eolChar && strlen($spaces['content']) !== $indent ) { $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; @@ -102,7 +102,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $phpcsFile->fixer->replaceToken($commentStart - 1, str_repeat(' ', $indent)); } } elseif ($spaces['code'] === T_WHITESPACE - && $spaces['content'] === "\n" + && $spaces['content'] === $phpcsFile->eolChar && $indent > 0 ) { $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; @@ -113,7 +113,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $fix = $phpcsFile->addFixableError($error, $commentStart, null, $data); if ($fix) { - $phpcsFile->fixer->replaceToken($commentStart - 1, "\n" . str_repeat(' ', $indent)); + $phpcsFile->fixer->replaceToken($commentStart - 1, $phpcsFile->eolChar . str_repeat(' ', $indent)); } } @@ -123,7 +123,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) while ($next = $phpcsFile->findNext($search, $from + 1, $commentEnd + 1)) { $spaces = $tokens[$next - 1]; - if ($spaces['content'] == "\n") { + if ($spaces['content'] === $phpcsFile->eolChar) { $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; $data = [ $indent + 1, @@ -132,7 +132,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $fix = $phpcsFile->addFixableError($error, $next, null, $data); if ($fix) { - $phpcsFile->fixer->replaceToken($next - 1, "\n" . ' '); + $phpcsFile->fixer->replaceToken($next - 1, $phpcsFile->eolChar . ' '); } } elseif ($spaces['code'] == T_DOC_COMMENT_WHITESPACE && strlen($spaces['content']) !== $indent + 1 diff --git a/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index dca15b1e..22d355a3 100644 --- a/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -75,7 +75,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) // Check if this is not before a comment at the end of the line if ($tokens[$stackPtr + 2]['code'] !== T_COMMENT && $tokens[$stackPtr + 3]['code'] !== T_WHITESPACE - && $tokens[$stackPtr + 3]['content'] !== "\n" + && $tokens[$stackPtr + 3]['content'] !== $phpcsFile->eolChar ) { if ($tokens[$stackPtr + 2]['code'] === T_DOC_COMMENT_OPEN_TAG) { $phpcsFile->addError( From 1376b667787ac5ec712dcbe199a00176f774037f Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 15 Nov 2016 18:18:23 +0000 Subject: [PATCH 007/225] Comments fix --- ZendCodingStandard/Tests/TestCase.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/ZendCodingStandard/Tests/TestCase.php b/ZendCodingStandard/Tests/TestCase.php index 64275619..60989760 100644 --- a/ZendCodingStandard/Tests/TestCase.php +++ b/ZendCodingStandard/Tests/TestCase.php @@ -39,7 +39,6 @@ protected function getTestFiles($testFileBase) } $path = $file->getPathname(); - // if (substr($path, 9, strlen($testFileBase)) === $testFileBase) if ($path !== $testFileBase . 'php' && substr($path, -5) !== 'fixed') { $testFiles[] = $path; } @@ -137,12 +136,10 @@ public function generateFailureMessages(PHP_CodeSniffer_File $file) throw new PHP_CodeSniffer_Exception('getWarningList() must return an array'); } - /* - We merge errors and warnings together to make it easier - to iterate over them and produce the errors string. In this way, - we can report on errors and warnings in the same line even though - it's not really structured to allow that. - */ + // We merge errors and warnings together to make it easier + // to iterate over them and produce the errors string. In this way, + // we can report on errors and warnings in the same line even though + // it's not really structured to allow that. $allProblems = []; $failureMessages = []; From d60dba82ea940b013cd9ccffe477362f641c7dbd Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 15 Nov 2016 18:18:46 +0000 Subject: [PATCH 008/225] Added tests for UnusedUseStatement sniff --- .../Classes/UnusedUseStatementUnitTest.inc | 62 +++++++++++++++++++ .../UnusedUseStatementUnitTest.inc.fixed | 56 +++++++++++++++++ .../Classes/UnusedUseStatementUnitTest.php | 24 +++++++ 3 files changed, 142 insertions(+) create mode 100644 ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.php diff --git a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc new file mode 100644 index 00000000..aa1e6b2f --- /dev/null +++ b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc @@ -0,0 +1,62 @@ + 1, + 11 => 1, + 13 => 1, + 19 => 1, + 20 => 1, + 21 => 1, + ]; + } +} From 815858f9f294389ff6a062f9eff7f4cc714a89cb Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 17 Nov 2016 13:37:38 +0000 Subject: [PATCH 009/225] Removed redundant brackets --- .../Classes/UnusedUseStatementSniff.php | 20 +++++++++---------- .../Commenting/FunctionCommentSniff.php | 18 ++++++++--------- .../Commenting/VariableCommentSniff.php | 6 +++--- .../ValidVariableNameSniff.php | 2 +- .../Sniffs/PHP/TypeCastingSniff.php | 3 +-- .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 2 +- 6 files changed, 25 insertions(+), 26 deletions(-) diff --git a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php index 9abaf9c0..d48174c3 100644 --- a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php +++ b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php @@ -57,7 +57,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $classPtr = $phpcsFile->findPrevious( PHP_CodeSniffer_Tokens::$emptyTokens, - ($semiColon - 1), + $semiColon - 1, null, true ); @@ -69,7 +69,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) // Search where the class name is used. PHP treats class names case // insensitive, that's why we cannot search for the exact class name string // and need to iterate over all T_STRING tokens in the file. - $classUsed = $phpcsFile->findNext([T_STRING, T_DOC_COMMENT_STRING], ($classPtr + 1)); + $classUsed = $phpcsFile->findNext([T_STRING, T_DOC_COMMENT_STRING], $classPtr + 1); $className = $tokens[$classPtr]['content']; $lowerClassName = strtolower($className); @@ -79,7 +79,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) // Check if the use statement does aliasing with the "as" keyword. Aliasing // is allowed even in the same namespace. - $aliasUsed = $phpcsFile->findPrevious(T_AS, ($classPtr - 1), $stackPtr); + $aliasUsed = $phpcsFile->findPrevious(T_AS, $classPtr - 1, $stackPtr); if ($namespacePtr !== false && $aliasUsed === false) { $nsEnd = $phpcsFile->findNext( @@ -89,26 +89,26 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) T_DOC_COMMENT_STRING, T_WHITESPACE, ], - ($namespacePtr + 1), + $namespacePtr + 1, null, true ); - $namespace = trim($phpcsFile->getTokensAsString(($namespacePtr + 1), ($nsEnd - $namespacePtr - 1))); + $namespace = trim($phpcsFile->getTokensAsString($namespacePtr + 1, $nsEnd - $namespacePtr - 1)); - $useNamespacePtr = $phpcsFile->findNext([T_STRING], ($stackPtr + 1)); + $useNamespacePtr = $phpcsFile->findNext([T_STRING], $stackPtr + 1); $useNamespaceEnd = $phpcsFile->findNext( [ T_NS_SEPARATOR, T_STRING, ], - ($useNamespacePtr + 1), + $useNamespacePtr + 1, null, true ); $useNamespace = rtrim( $phpcsFile->getTokensAsString( $useNamespacePtr, - ($useNamespaceEnd - $useNamespacePtr - 1) + $useNamespaceEnd - $useNamespacePtr - 1 ), '\\' ); @@ -133,7 +133,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) ) { $beforeUsage = $phpcsFile->findPrevious( $emptyTokens, - ($classUsed - 1), + $classUsed - 1, null, true ); @@ -165,7 +165,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } } - $classUsed = $phpcsFile->findNext([T_STRING, T_DOC_COMMENT_STRING], ($classUsed + 1)); + $classUsed = $phpcsFile->findNext([T_STRING, T_DOC_COMMENT_STRING], $classUsed + 1); } $warning = 'Unused use statement: ' . $className; diff --git a/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 9a1adfd4..c9fddea7 100644 --- a/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -95,7 +95,7 @@ protected function processReturn(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co $fix = $phpcsFile->addFixableError($error, $return, 'InvalidReturn', $data); if ($fix) { - $phpcsFile->fixer->replaceToken(($return + 2), $suggestedType); + $phpcsFile->fixer->replaceToken($return + 2, $suggestedType); } } @@ -125,7 +125,7 @@ protected function processReturn(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co if ($returnToken !== $endToken) { // If the function is not returning anything, just // exiting, then there is no problem. - $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); + $semicolon = $phpcsFile->findNext(T_WHITESPACE, $returnToken + 1, null, true); if ($tokens[$semicolon]['code'] !== T_SEMICOLON) { $error = 'Function return type is void, but function contains return statement'; $phpcsFile->addError($error, $return, 'InvalidReturnVoid'); @@ -148,7 +148,7 @@ protected function processReturn(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co $error = 'Function return type is not void, but function has no return statement'; $phpcsFile->addError($error, $return, 'InvalidNoReturn'); } else { - $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); + $semicolon = $phpcsFile->findNext(T_WHITESPACE, $returnToken + 1, null, true); if ($tokens[$semicolon]['code'] === T_SEMICOLON) { $error = 'Function return type is not void, but function is returning void here'; $phpcsFile->addError($error, $returnToken, 'InvalidReturnNotVoid'); @@ -218,13 +218,13 @@ protected function processThrows(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co $firstChar = $comment{0}; if (strtoupper($firstChar) !== $firstChar) { $error = '@throws tag comment must start with a capital letter'; - $phpcsFile->addError($error, ($tag + 2), 'ThrowsNotCapital'); + $phpcsFile->addError($error, $tag + 2, 'ThrowsNotCapital'); } $lastChar = substr($comment, -1); if ($lastChar !== '.') { $error = '@throws tag comment must end with a full stop'; - $phpcsFile->addError($error, ($tag + 2), 'ThrowsNoFullStop'); + $phpcsFile->addError($error, $tag + 2, 'ThrowsNoFullStop'); } } } @@ -276,7 +276,7 @@ protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co if (! empty($matches)) { $typeLen = strlen($matches[1]); $type = trim($matches[1]); - $typeSpace = ($typeLen - strlen($type)); + $typeSpace = $typeLen - strlen($type); $typeLen = strlen($type); if ($typeLen > $maxType) { $maxType = $typeLen; @@ -295,7 +295,7 @@ protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co $comment = $matches[4]; $commentLines[] = [ 'comment' => $comment, - 'token' => ($tag + 2), + 'token' => $tag + 2, 'indent' => $varSpace, ]; @@ -458,7 +458,7 @@ protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co $foundParams[] = $param['var']; // Check number of spaces after the type. - $spaces = ($maxType - strlen($param['type']) + 1); + $spaces = $maxType - strlen($param['type']) + 1; if ($param['type_space'] !== $spaces) { $error = 'Expected %s spaces after parameter type; %s found'; $data = [ @@ -527,7 +527,7 @@ protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co } // Check number of spaces after the var name. - $spaces = ($maxVar - strlen($param['var']) + 1); + $spaces = $maxVar - strlen($param['var']) + 1; if ($param['var_space'] !== $spaces) { $error = 'Expected %s spaces after parameter name; %s found'; $data = [ diff --git a/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php b/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php index 03312017..16b68cdc 100644 --- a/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php +++ b/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php @@ -46,7 +46,7 @@ public function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr) T_WHITESPACE, ]; - $commentEnd = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + $commentEnd = $phpcsFile->findPrevious($ignore, $stackPtr - 1, null, true); if ($commentEnd === false || ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG && $tokens[$commentEnd]['code'] !== T_COMMENT) @@ -120,10 +120,10 @@ public function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $suggestedType, $varType, ]; - $fix = $phpcsFile->addFixableError($error, ($foundVar + 2), 'IncorrectVarType', $data); + $fix = $phpcsFile->addFixableError($error, $foundVar + 2, 'IncorrectVarType', $data); if ($fix) { - $phpcsFile->fixer->replaceToken(($foundVar + 2), $suggestedType); + $phpcsFile->fixer->replaceToken($foundVar + 2, $suggestedType); } } } diff --git a/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php b/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php index 8cb4dbec..53bbb0e4 100644 --- a/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php +++ b/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -41,7 +41,7 @@ protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr) return; } - $objOperator = $phpcsFile->findPrevious([T_WHITESPACE], ($stackPtr - 1), null, true); + $objOperator = $phpcsFile->findPrevious([T_WHITESPACE], $stackPtr - 1, null, true); if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON) { return; // skip MyClass::$variable, there might be no control over the declaration } diff --git a/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php index 0afdcdb7..bb43b3dd 100644 --- a/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php +++ b/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -22,7 +22,6 @@ * @link http://pear.php.net/package/PHP_CodeSniffer_CakePHP * @license http://www.opensource.org/licenses/mit-license.php MIT License */ - /** * Asserts that type casts are in the short form: * - bool instead of boolean @@ -59,7 +58,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) // Process !! casts if ($tokens[$stackPtr]['code'] == T_BOOLEAN_NOT) { - $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $nextToken = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if (! $nextToken) { return; } diff --git a/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index 22d355a3..eba4812d 100644 --- a/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -41,7 +41,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) if (isset(PHP_CodeSniffer_Tokens::$emptyTokens[$prevType])) { $nonSpace = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr - 2, null, true); $expected = $tokens[$nonSpace]['content'] . ','; - $found = $phpcsFile->getTokensAsString($nonSpace, ($stackPtr - $nonSpace)) . ','; + $found = $phpcsFile->getTokensAsString($nonSpace, $stackPtr - $nonSpace) . ','; $error = 'Space found before comma; expected "%s" but found "%s"'; $data = [ $expected, From 5bdde460ae18cab40238d7ceee2a355df404a025 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 27 Nov 2016 17:19:43 +0000 Subject: [PATCH 010/225] DocComment sniffs update + tests --- .../Sniffs/Commenting/DocCommentSniff.php | 493 +++++++++++++++--- .../Sniffs/PHP/TypeCastingSniff.php | 3 +- .../Tests/Commenting/DocCommentUnitTest.1.inc | 44 ++ .../Commenting/DocCommentUnitTest.1.inc.fixed | 21 + .../Tests/Commenting/DocCommentUnitTest.2.inc | 23 + .../Commenting/DocCommentUnitTest.2.inc.fixed | 23 + .../Tests/Commenting/DocCommentUnitTest.3.inc | 21 + .../Commenting/DocCommentUnitTest.3.inc.fixed | 28 + .../Tests/Commenting/DocCommentUnitTest.4.inc | 33 ++ .../Commenting/DocCommentUnitTest.4.inc.fixed | 35 ++ .../Tests/Commenting/DocCommentUnitTest.5.inc | 23 + .../Commenting/DocCommentUnitTest.5.inc.fixed | 23 + .../Tests/Commenting/DocCommentUnitTest.6.inc | 23 + .../Commenting/DocCommentUnitTest.6.inc.fixed | 23 + .../Tests/Commenting/DocCommentUnitTest.7.inc | 17 + .../Commenting/DocCommentUnitTest.7.inc.fixed | 20 + .../Tests/Commenting/DocCommentUnitTest.8.inc | 19 + .../Commenting/DocCommentUnitTest.8.inc.fixed | 23 + .../Tests/Commenting/DocCommentUnitTest.9.inc | 37 ++ .../Commenting/DocCommentUnitTest.9.inc.fixed | 25 + .../Tests/Commenting/DocCommentUnitTest.inc | 124 +++++ .../Commenting/DocCommentUnitTest.inc.fixed | 121 +++++ .../Tests/Commenting/DocCommentUnitTest.php | 141 +++++ 23 files changed, 1265 insertions(+), 78 deletions(-) create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.1.inc create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.1.inc.fixed create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.2.inc create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.2.inc.fixed create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.3.inc create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.3.inc.fixed create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.4.inc create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.4.inc.fixed create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.5.inc create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.5.inc.fixed create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.6.inc create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.6.inc.fixed create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.7.inc create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.7.inc.fixed create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.8.inc create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.8.inc.fixed create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.9.inc create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.9.inc.fixed create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.php diff --git a/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index 3ec58070..610e981d 100644 --- a/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -1,8 +1,4 @@ checkIfEmpty($phpcsFile, $commentStart, $commentEnd)) { + return; + } + + $this->checkBeforeOpen($phpcsFile, $commentStart); + $this->checkAfterClose($phpcsFile, $commentStart, $commentEnd); + $this->checkCommentIndents($phpcsFile, $commentStart, $commentEnd); + + // Doc block comment in one line. if ($tokens[$commentStart]['line'] == $tokens[$commentEnd]['line']) { + $this->checkSpacesInOneLineComment($phpcsFile, $commentStart, $commentEnd); + return; } - $short = $phpcsFile->findNext( - [ - T_DOC_COMMENT_WHITESPACE, - T_DOC_COMMENT_STAR, - ], - $stackPtr + 1, - $commentEnd, - true - ); - if ($short === false) { - // No content at all. - $error = 'Doc comment is empty.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty'); + $this->checkAfterOpen($phpcsFile, $commentStart); + $this->checkBeforeClose($phpcsFile, $commentEnd); + + $this->checkSpacesAfterStar($phpcsFile, $commentStart, $commentEnd); + $this->checkBlankLinesInComment($phpcsFile, $commentStart, $commentEnd); + } + + private function checkIfEmpty(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) + { + $tokens = $phpcsFile->getTokens(); + + $empty = [ + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STAR, + ]; + + $next = $commentStart; + while ($next = $phpcsFile->findNext($empty, $next + 1, $commentEnd, true)) { + if ($tokens[$next]['code'] === T_DOC_COMMENT_STRING + && preg_match('/^[*\s]+$/', $tokens[$next]['content']) + ) { + continue; + } + + return false; + } + + $error = 'Doc comment is empty.'; + $fix = $phpcsFile->addFixableError($error, $commentStart, 'Empty'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $commentStart; $i <= $commentEnd; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + if ($tokens[$commentStart - 1]['code'] === T_WHITESPACE + && strpos($tokens[$commentStart - 1]['content'], $phpcsFile->eolChar) === false + ) { + $phpcsFile->fixer->replaceToken($commentStart - 1, ''); + if ($tokens[$commentStart - 2]['code'] === T_WHITESPACE + && strpos($tokens[$commentStart - 2]['content'], $phpcsFile->eolChar) !== false + && $tokens[$commentEnd + 1]['code'] === T_WHITESPACE + && strpos($tokens[$commentEnd + 1]['content'], $phpcsFile->eolChar) !== false + ) { + $phpcsFile->fixer->replaceToken($commentStart - 2, ''); + } + } elseif ($tokens[$commentStart - 1]['code'] === T_WHITESPACE + && strpos($tokens[$commentStart - 1]['content'], $phpcsFile->eolChar) !== false + && $tokens[$commentEnd + 1]['code'] === T_WHITESPACE + && strpos($tokens[$commentEnd + 1]['content'], $phpcsFile->eolChar) !== false + ) { + $phpcsFile->fixer->replaceToken($commentStart - 1, ''); + } elseif ($tokens[$commentStart - 1]['code'] === T_OPEN_TAG + && ($next = $phpcsFile->findNext([T_WHITESPACE], $commentEnd + 1, null, true)) + && $tokens[$next]['line'] > $tokens[$commentEnd]['line'] + 1 + ) { + $phpcsFile->fixer->replaceToken($commentEnd + 1, ''); + } + $phpcsFile->fixer->endChangeset(); + } + + return true; + } + + private function checkBeforeOpen(PHP_CodeSniffer_File $phpcsFile, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + $previous = $phpcsFile->findPrevious([T_WHITESPACE], $commentStart - 1, null, true); + if ($tokens[$previous]['line'] === $tokens[$commentStart]['line']) { + $error = 'The open comment tag must be the only content on the line.'; + $fix = $phpcsFile->addFixableError($error, $commentStart); + if ($fix) { + $nonEmpty = $phpcsFile->findPrevious([T_WHITESPACE], $commentStart - 1, null, true); $phpcsFile->fixer->beginChangeset(); - for ($i = $commentStart; $i <= $commentEnd; $i++) { - $phpcsFile->fixer->replaceToken($i, ''); + $prev = $commentStart; + while ($prev = $phpcsFile->findPrevious([T_WHITESPACE], $prev - 1, $nonEmpty)) { + $phpcsFile->fixer->replaceToken($prev, ''); } + $phpcsFile->fixer->addNewline($commentStart - 1); $phpcsFile->fixer->endChangeset(); } + } elseif ($tokens[$previous]['line'] === $tokens[$commentStart]['line'] - 1 + && $tokens[$previous]['code'] !== T_OPEN_TAG + && $tokens[$previous]['code'] !== T_OPEN_CURLY_BRACKET + ) { + $error = 'Missing blank line before doc comment.'; + $fix = $phpcsFile->addFixableError($error, $commentStart); - return; + if ($fix) { +// if ($tokens[$commentStart - 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->addNewlineBefore($commentStart - 1); +// } else { +// $phpcsFile->fixer->addNewlineBefore($commentStart); +// } + } + } + } + + private function checkAfterOpen(PHP_CodeSniffer_File $phpcsFile, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + $next = $phpcsFile->findNext([T_DOC_COMMENT_WHITESPACE], $commentStart + 1, null, true); + if ($tokens[$next]['line'] === $tokens[$commentStart]['line']) { + $error = 'The open comment tag must be the only content on the line.'; + $fix = $phpcsFile->addFixableError($error, $commentStart); + + if ($fix) { + $indentToken = $tokens[$commentStart - 1]; + if ($indentToken['code'] === T_WHITESPACE + && $indentToken['line'] === $tokens[$commentStart]['line'] + ) { + $indent = strlen($indentToken['content']); + } else { + $indent = 0; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($commentStart); + if ($tokens[$commentStart + 1]['code'] === T_DOC_COMMENT_WHITESPACE) { + $phpcsFile->fixer->replaceToken($commentStart + 1, str_repeat(' ', $indent)); + if ($tokens[$commentStart + 2]['code'] !== T_DOC_COMMENT_STAR) { + $phpcsFile->fixer->addContent($commentStart + 1, '* '); + } + } + $phpcsFile->fixer->endChangeset(); + } } + } + + private function checkBeforeClose(PHP_CodeSniffer_File $phpcsFile, $commentEnd) + { + $tokens = $phpcsFile->getTokens(); - if ($tokens[$commentEnd + 1]['content'] !== $phpcsFile->eolChar) { + $previous = $phpcsFile->findPrevious([T_DOC_COMMENT_WHITESPACE], $commentEnd - 1, null, true); + if ($tokens[$previous]['line'] === $tokens[$commentEnd]['line']) { $error = 'The close comment tag must be the only content on the line.'; $fix = $phpcsFile->addFixableError($error, $commentEnd); if ($fix) { - $phpcsFile->fixer->addNewline($commentEnd); + $phpcsFile->fixer->beginChangeset(); + $content = $tokens[$commentEnd - 1]['content']; + if (trim($content) . ' ' !== $content) { + $phpcsFile->fixer->replaceToken($commentEnd - 1, trim($content)); + } + $phpcsFile->fixer->addNewlineBefore($commentEnd); + $phpcsFile->fixer->endChangeset(); } + } + } + + private function checkAfterClose(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) + { + $tokens = $phpcsFile->getTokens(); + + $allowEmptyLineBefore = [ + T_NAMESPACE, + T_USE, + ]; + $next = $phpcsFile->findNext([T_WHITESPACE], $commentEnd + 1, null, true); + + if (! $next) { + $error = 'Doc comment is not allowed at the end of the file.'; + $phpcsFile->addError($error, $commentStart); return; } - $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_WHITESPACE], $commentEnd - 1, null, true); - if ($tokens[$prev]['content'] !== $phpcsFile->eolChar - && $tokens[$prev]['line'] === $tokens[$commentEnd]['line'] - ) { + if ($tokens[$commentEnd]['line'] === $tokens[$next]['line']) { $error = 'The close comment tag must be the only content on the line.'; $fix = $phpcsFile->addFixableError($error, $commentEnd); if ($fix) { - $phpcsFile->fixer->addNewlineBefore($commentEnd); + $phpcsFile->fixer->beginChangeset(); + $newLine = $commentEnd; + if ($tokens[$commentEnd + 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($commentEnd + 1, ''); + $newLine++; + } + $phpcsFile->fixer->addNewline($newLine); + $phpcsFile->fixer->endChangeset(); } - } + } elseif ($tokens[$next]['line'] > $tokens[$commentEnd]['line'] + 1 + && ! in_array($tokens[$next]['code'], $allowEmptyLineBefore) + ) { + $error = 'Additional blank lines found after doc comment.'; + $fix = $phpcsFile->addFixableError($error, $commentEnd + 2, 'BlankLinesAfter'); - if ($tokens[$commentEnd + 2]['content'] === $phpcsFile->eolChar) { - // There is empty line after doc block. - $before = $tokens[$commentStart - 1]; + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $commentEnd + 1; $i < $next; $i++) { + if ($tokens[$i + 1]['line'] === $tokens[$next]['line']) { + break; + } - $indent = $before['code'] == T_OPEN_TAG || $before['content'] == $phpcsFile->eolChar - ? 0 - : strlen($before['content']); - } elseif ($tokens[$commentEnd + 2]['code'] == T_WHITESPACE) { - $indent = strlen($tokens[$commentEnd + 2]['content']); - } else { - $indent = 0; + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->endChangeset(); + } } + } - // First line of the doc comment. - $spaces = $tokens[$commentStart - 1]; - if ($spaces['code'] === T_WHITESPACE - && $spaces['content'] !== $phpcsFile->eolChar - && strlen($spaces['content']) !== $indent + private function checkSpacesInOneLineComment(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) + { + $tokens = $phpcsFile->getTokens(); + + // Check, if there is exactly one space after opening tag. + if ($tokens[$commentStart + 1]['code'] === T_DOC_COMMENT_WHITESPACE + && $tokens[$commentStart + 1]['content'] !== ' ' ) { - $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; - $data = [ - $indent, - strlen($spaces['content']), - ]; - $fix = $phpcsFile->addFixableError($error, $commentStart, null, $data); + $error = 'Expected 1 space after opening tag of one line doc block comment.'; + $fix = $phpcsFile->addFixableError($error, $commentStart + 1); if ($fix) { - $phpcsFile->fixer->replaceToken($commentStart - 1, str_repeat(' ', $indent)); + $phpcsFile->fixer->replaceToken($commentStart + 1, ' '); } - } elseif ($spaces['code'] === T_WHITESPACE - && $spaces['content'] === $phpcsFile->eolChar - && $indent > 0 - ) { - $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; - $data = [ - $indent, - 0, - ]; - $fix = $phpcsFile->addFixableError($error, $commentStart, null, $data); + } elseif ($tokens[$commentStart + 1]['code'] !== T_DOC_COMMENT_WHITESPACE) { + // This case is currently not supported. + // Comment /**@var null $name; */ is not recognized as doc-block comment. + $error = 'Expected 1 space after opening tag of one line doc block comment.'; + $fix = $phpcsFile->addFixableError($error, $commentStart); if ($fix) { - $phpcsFile->fixer->replaceToken($commentStart - 1, $phpcsFile->eolChar . str_repeat(' ', $indent)); + $phpcsFile->fixer->addContent($commentStart, ' '); } } - // Rest of the doc comment. - $from = $commentStart; + // Check, if there is exactly one space before closing tag. + $content = $tokens[$commentEnd - 1]['content']; + if (trim($content) . ' ' !== $content) { + $error = 'Expected 1 space before closing tag of one line doc block comment.'; + $fix = $phpcsFile->addFixableError($error, $commentEnd - 1); + + if ($fix) { + $phpcsFile->fixer->replaceToken($commentEnd - 1, trim($content) . ' '); + } + } + } + + private function checkSpacesAfterStar(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) + { + $tokens = $phpcsFile->getTokens(); + + $next = $commentStart; $search = [T_DOC_COMMENT_STAR, T_DOC_COMMENT_CLOSE_TAG]; - while ($next = $phpcsFile->findNext($search, $from + 1, $commentEnd + 1)) { - $spaces = $tokens[$next - 1]; + while ($next = $phpcsFile->findNext($search, $next + 1, $commentEnd + 1)) { + if ($tokens[$next]['code'] === T_DOC_COMMENT_STAR + && $tokens[$next + 1]['code'] !== T_DOC_COMMENT_WHITESPACE + || ($tokens[$next + 1]['code'] === T_DOC_COMMENT_WHITESPACE + && strpos($tokens[$next + 1]['content'], $phpcsFile->eolChar) === false) + ) { + if ($tokens[$next + 1]['code'] !== T_DOC_COMMENT_WHITESPACE) { + $error = 'There must be exactly one space between star and comment.'; + $fix = $phpcsFile->addFixableError($error, $next); + + if ($fix) { + $phpcsFile->fixer->addContent($next, ' '); + } + } elseif ($tokens[$next + 1]['content'] !== ' ' + && ($tokens[$next + 2]['content'][0] === '@' + || $tokens[$next + 1]['line'] === $tokens[$commentStart]['line'] + 1) + ) { + $error = 'There must be exactly one space between star and comment.'; + $fix = $phpcsFile->addFixableError($error, $next + 1); + + if ($fix) { + $phpcsFile->fixer->replaceToken($next + 1, ' '); + } + } + } + } + } + + private function checkBlankLinesInComment(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) + { + $tokens = $phpcsFile->getTokens(); + + $empty = [ + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STAR, + ]; + + // Additional blank lines at the beginning of doc block. + $next = $phpcsFile->findNext($empty, $commentStart + 1, null, true); + if ($tokens[$next]['line'] > $tokens[$commentStart]['line'] + 1) { + $error = 'Additional blank lines found at the beginning of doc comment.'; + $fix = $phpcsFile->addFixableError($error, $commentStart + 2, 'SpacingBefore'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $commentStart + 1; $i < $next; $i++) { + if ($tokens[$i + 1]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->endChangeset(); + } + } + + // Additional blank lines at the and of doc block. + $previous = $phpcsFile->findPrevious($empty, $commentEnd - 1, null, true); + if ($tokens[$previous]['line'] < $tokens[$commentEnd]['line'] - 1) { + $error = 'Additional blank lines found at the end of doc comment.'; + $fix = $phpcsFile->addFixableError($error, $previous + 2, 'SpacingAfter'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $previous + 1; $i < $commentEnd; $i++) { + if ($tokens[$i + 1]['line'] === $tokens[$commentEnd]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->endChangeset(); + } + } - if ($spaces['content'] === $phpcsFile->eolChar) { + // Check for double blank lines. + $from = $phpcsFile->findNext($empty, $commentStart + 1, null, true); + $to = $phpcsFile->findPrevious($empty, $commentEnd - 1, null, true); + + while ($next = $phpcsFile->findNext($empty, $from + 1, $to, true)) { + if ($tokens[$next]['line'] > $tokens[$from]['line'] + 2) { + $error = 'More than one blank line between parts of doc block.'; + $i = 0; + while ($token = $phpcsFile->findNext([T_DOC_COMMENT_STAR], $from + 1, $next - 2)) { + if ($i++ > 0) { + $fix = $phpcsFile->addFixableError($error, $token); + + if ($fix) { + $firstOnLine = $phpcsFile->findFirstOnLine($empty, $token); + for ($n = $firstOnLine; $n <= $token + 1; $n++) { + $phpcsFile->fixer->replaceToken($n, ''); + } + } + } + + $from = $token; + } + } + + $from = $next; + } + } + + private function checkCommentIndents(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) + { + $tokens = $phpcsFile->getTokens(); + + $allowEmptyLineBefore = [ + T_NAMESPACE, + T_USE, + ]; + + $next = $phpcsFile->findNext([T_WHITESPACE], $commentEnd + 1, null, true); + + // There is something exactly in the next line. + if ($next && $tokens[$next]['line'] === $tokens[$commentEnd]['line'] + 1) { + // Check indent of the next line. + if ($tokens[$next - 1]['code'] === T_WHITESPACE + && strpos($tokens[$next - 1]['content'], $phpcsFile->eolChar) === false + ) { + $indent = strlen($tokens[$next - 1]['content']); + } else { + $indent = 0; + } + } elseif (! $next + || $tokens[$next]['line'] > $tokens[$commentEnd]['line'] + 1 + && in_array($tokens[$next]['code'], $allowEmptyLineBefore) + ) { + $indent = 0; + } else { + return; + } + + // The open tag is alone in the line. + $previous = $phpcsFile->findPrevious([T_WHITESPACE], $commentStart - 1, null, true); + if ($tokens[$previous]['line'] < $tokens[$commentStart]['line']) { + // Check if comment starts with the same indent. + $spaces = $tokens[$commentStart - 1]; + if ($spaces['code'] === T_WHITESPACE + && strpos($spaces['content'], $phpcsFile->eolChar) === false + && strlen($spaces['content']) !== $indent + ) { $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; $data = [ - $indent + 1, - 0, + $indent, + strlen($spaces['content']), ]; - $fix = $phpcsFile->addFixableError($error, $next, null, $data); + $fix = $phpcsFile->addFixableError($error, $commentStart, null, $data); if ($fix) { - $phpcsFile->fixer->replaceToken($next - 1, $phpcsFile->eolChar . ' '); + $phpcsFile->fixer->replaceToken($commentStart - 1, str_repeat(' ', $indent)); } - } elseif ($spaces['code'] == T_DOC_COMMENT_WHITESPACE - && strlen($spaces['content']) !== $indent + 1 + } elseif ($spaces['code'] === T_WHITESPACE + && strpos($spaces['content'], $phpcsFile->eolChar) !== false + && $indent > 0 ) { $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; $data = [ - $indent + 1, - strlen($spaces['content']), + $indent, + 0, ]; - $fix = $phpcsFile->addFixableError($error, $next, null, $data); + $fix = $phpcsFile->addFixableError($error, $commentStart, null, $data); if ($fix) { - $phpcsFile->fixer->replaceToken($next - 1, str_repeat(' ', $indent + 1)); + $phpcsFile->fixer->replaceToken( + $commentStart - 1, + $phpcsFile->eolChar . str_repeat(' ', $indent) + ); + } + } + } + + // This is one-line doc comment. + if ($tokens[$commentStart]['line'] === $tokens[$commentEnd]['line']) { + return; + } + + // Rest of the doc comment. + $from = $commentStart; + $search = [T_DOC_COMMENT_STAR, T_DOC_COMMENT_CLOSE_TAG]; + while ($next = $phpcsFile->findNext($search, $from + 1, $commentEnd + 1)) { + if ($tokens[$next]['line'] !== $tokens[$from]['line']) { + $spaces = $tokens[$next - 1]; + + if (strpos($spaces['content'], $phpcsFile->eolChar) !== false) { + $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; + $data = [ + $indent + 1, + 0, + ]; + $fix = $phpcsFile->addFixableError($error, $next, null, $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($next - 1, $phpcsFile->eolChar . ' '); + } + } elseif ($spaces['code'] == T_DOC_COMMENT_WHITESPACE + && strlen($spaces['content']) !== $indent + 1 + ) { + $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; + $data = [ + $indent + 1, + strlen($spaces['content']), + ]; + $fix = $phpcsFile->addFixableError($error, $next, null, $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($next - 1, str_repeat(' ', $indent + 1)); + } } } diff --git a/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php index bb43b3dd..d305ba35 100644 --- a/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php +++ b/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -21,8 +21,7 @@ * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://pear.php.net/package/PHP_CodeSniffer_CakePHP * @license http://www.opensource.org/licenses/mit-license.php MIT License - */ -/** + * * Asserts that type casts are in the short form: * - bool instead of boolean * - int instead of integer diff --git a/ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.1.inc b/ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.1.inc new file mode 100644 index 00000000..b2bd77c9 --- /dev/null +++ b/ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.1.inc @@ -0,0 +1,44 @@ + 1, + 8 => 1, + 13 => 1, + 18 => 1, + 23 => 1, + 26 => 1, + 27 => 1, + 28 => 1, + 31 => 1, + 38 => 1, + 42 => 1, + ]; + case 'DocCommentUnitTest.2.inc': + return [ + 3 => 1, + 9 => 1, + 14 => 1, + 19 => 1, + ]; + case 'DocCommentUnitTest.3.inc': + return [ + 1 => 1, + 5 => 1, + 9 => 1, + 14 => 1, + 18 => 1, + ]; + case 'DocCommentUnitTest.4.inc': + return [ + 4 => 1, + 10 => 1, + 14 => 1, + 16 => 1, + 21 => 1, + 25 => 1, + 30 => 1, + ]; + case 'DocCommentUnitTest.5.inc': + return [ + 3 => 1, + 4 => 1, + 10 => 1, + 12 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 20 => 1, + ]; + case 'DocCommentUnitTest.6.inc': + return [ + 2 => 2, + 8 => 1, + 11 => 1, + 14 => 2, + 17 => 1, + // 20 => 2, // not yet supported + ]; + case 'DocCommentUnitTest.7.inc': + return [ + 2 => 1, + 9 => 1, + 13 => 1, + ]; + case 'DocCommentUnitTest.8.inc': + return [ + 3 => 1, + 8 => 1, + 12 => 1, + 16 => 1, + ]; + case 'DocCommentUnitTest.9.inc': + return [ + 4 => 1, + 10 => 1, + 13 => 1, + 18 => 1, + 25 => 1, + 27 => 1, + 32 => 1, + ]; + } + + return [ + 3 => 1, + 8 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 16 => 1, + 17 => 1, + 25 => 1, + 26 => 1, + 29 => 1, + 32 => 1, + 35 => 1, + 36 => 1, + 37 => 1, + 42 => 1, + 45 => 1, + 48 => 1, + 53 => 2, + 55 => 1, + 59 => 1, + 62 => 1, + 65 => 1, + 70 => 1, + 73 => 1, + 75 => 1, + 79 => 1, + 80 => 1, + 81 => 1, + 84 => 1, + 89 => 1, + 90 => 1, + 94 => 1, + 96 => 1, + 99 => 1, + 103 => 1, + 104 => 1, + 110 => 1, + 111 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 35288e59b7f5a7a8fd5c710d714622b4fde9dd46 Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 28 Nov 2016 09:53:32 +0000 Subject: [PATCH 011/225] Unused use statement fix - Annotations checks - per @Gamewalker --- .../Classes/UnusedUseStatementSniff.php | 30 +++++++++++-------- .../Classes/UnusedUseStatementUnitTest.inc | 8 +++++ .../UnusedUseStatementUnitTest.inc.fixed | 8 +++++ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php index d48174c3..6d709b73 100644 --- a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php +++ b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php @@ -4,6 +4,8 @@ * @see http://jdon.at/1h0wb * @see https://github.com/squizlabs/PHP_CodeSniffer/pull/1106 * + * - added checks in annotations + * * @todo remove once merged to squizlabs/PHP_CodeSniffer (?) */ namespace ZendCodingStandard\Sniffs\Classes; @@ -69,7 +71,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) // Search where the class name is used. PHP treats class names case // insensitive, that's why we cannot search for the exact class name string // and need to iterate over all T_STRING tokens in the file. - $classUsed = $phpcsFile->findNext([T_STRING, T_DOC_COMMENT_STRING], $classPtr + 1); + $classUsed = $phpcsFile->findNext([T_STRING, T_DOC_COMMENT_STRING, T_DOC_COMMENT_TAG], $classPtr + 1); $className = $tokens[$classPtr]['content']; $lowerClassName = strtolower($className); @@ -121,7 +123,6 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $emptyTokens = PHP_CodeSniffer_Tokens::$emptyTokens; unset($emptyTokens[T_DOC_COMMENT_TAG]); - while ($classUsed !== false) { if (($tokens[$classUsed]['code'] == T_STRING && strtolower($tokens[$classUsed]['content']) === $lowerClassName) @@ -130,6 +131,11 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) '/(\s|\||^)' . preg_quote($lowerClassName) . '(\s|\||$|\[\])/i', $tokens[$classUsed]['content'] )) + || ($tokens[$classUsed]['code'] == T_DOC_COMMENT_TAG + && preg_match( + '/@' . preg_quote($lowerClassName) . '(\(|\\\\|$)/i', + $tokens[$classUsed]['content'] + )) ) { $beforeUsage = $phpcsFile->findPrevious( $emptyTokens, @@ -153,22 +159,22 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) ) { return; } + } elseif ($tokens[$beforeUsage]['code'] === T_DOC_COMMENT_TAG && + in_array( + $tokens[$beforeUsage]['content'], + ['@var', '@param', '@return', '@throws', '@method'] + ) + ) { + return; } else { - if ($tokens[$beforeUsage]['code'] === T_DOC_COMMENT_TAG && - in_array( - $tokens[$beforeUsage]['content'], - ['@var', '@param', '@return', '@throws', '@method'] - ) - ) { - return; - } + return; } } - $classUsed = $phpcsFile->findNext([T_STRING, T_DOC_COMMENT_STRING], $classUsed + 1); + $classUsed = $phpcsFile->findNext([T_STRING, T_DOC_COMMENT_STRING, T_DOC_COMMENT_TAG], $classUsed + 1); } - $warning = 'Unused use statement: ' . $className; + $warning = sprintf('Unused use statement "%s"', $className); $fix = $phpcsFile->addFixableWarning($warning, $stackPtr, 'UnusedUse'); if ($fix) { diff --git a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc index aa1e6b2f..fb0b412d 100644 --- a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc +++ b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc @@ -19,7 +19,15 @@ use Bar\Baz\Used9 as AliasUsed9; use Bar\Baz\Unused3; use Bar\Baz\Unused4 as AliasUnused4; use FooBar\Unused5; +use Used10; +use Used11; +use FooBar\Used12 as AliasUsed12; +/** + * @Used10 + * @Used11\Table + * @AliasUsed12(...) + */ class Foo { use Traits\MyTrait; diff --git a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed index 2f3acbe5..851c499f 100644 --- a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed +++ b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed @@ -13,7 +13,15 @@ use MyApp\Used6; use Used7 as AliasUsed7; use Bar\Baz\Used8; use Bar\Baz\Used9 as AliasUsed9; +use Used10; +use Used11; +use FooBar\Used12 as AliasUsed12; +/** + * @Used10 + * @Used11\Table + * @AliasUsed12(...) + */ class Foo { use Traits\MyTrait; From fc18e691322c9677e206bed54fa684419a6cb9d6 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 30 Nov 2016 10:19:59 +0000 Subject: [PATCH 012/225] Methods\LineAfter sniff update + tests --- .../Sniffs/Methods/LineAfterSniff.php | 42 +++++------------ .../Tests/Methods/LineAfterUnitTest.1.inc | 16 +++++++ .../Methods/LineAfterUnitTest.1.inc.fixed | 18 ++++++++ .../Tests/Methods/LineAfterUnitTest.2.inc | 26 +++++++++++ .../Methods/LineAfterUnitTest.2.inc.fixed | 30 ++++++++++++ .../Tests/Methods/LineAfterUnitTest.inc | 26 +++++++++++ .../Tests/Methods/LineAfterUnitTest.inc.fixed | 30 ++++++++++++ .../Tests/Methods/LineAfterUnitTest.php | 46 +++++++++++++++++++ 8 files changed, 204 insertions(+), 30 deletions(-) create mode 100644 ZendCodingStandard/Tests/Methods/LineAfterUnitTest.1.inc create mode 100644 ZendCodingStandard/Tests/Methods/LineAfterUnitTest.1.inc.fixed create mode 100644 ZendCodingStandard/Tests/Methods/LineAfterUnitTest.2.inc create mode 100644 ZendCodingStandard/Tests/Methods/LineAfterUnitTest.2.inc.fixed create mode 100644 ZendCodingStandard/Tests/Methods/LineAfterUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Methods/LineAfterUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Methods/LineAfterUnitTest.php diff --git a/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php b/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php index d5ec5f05..c96195a6 100644 --- a/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php +++ b/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php @@ -11,56 +11,38 @@ class LineAfterSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff { public function __construct() { - parent::__construct([T_CLASS, T_INTERFACE], [T_FUNCTION]); + parent::__construct([T_CLASS, T_INTERFACE, T_TRAIT], [T_FUNCTION]); } protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $tokens = $phpcsFile->getTokens(); - $prev = $phpcsFile->findPrevious( - array_merge(\PHP_CodeSniffer_Tokens::$methodPrefixes, [T_WHITESPACE]), - $stackPtr - 1, - null, - true - ); - - $visibility = $phpcsFile->findPrevious( - [T_PUBLIC, T_PROTECTED, T_PRIVATE], - $stackPtr - 1, - $prev - ); - - // Skip methods without visibility. - if (! $visibility) { - return; + // Methods with body. + if (isset($tokens[$stackPtr]['scope_closer'])) { + $closer = $tokens[$stackPtr]['scope_closer']; + } else { + $closer = $phpcsFile->findNext(T_SEMICOLON, $tokens[$stackPtr]['parenthesis_closer'] + 1); } - // Skip methods without body. - if (! isset($tokens[$stackPtr]['scope_closer'])) { - return; - } - - $scopeCloser = $tokens[$stackPtr]['scope_closer']; - - $contentAfter = $phpcsFile->findNext(T_WHITESPACE, $scopeCloser + 1, null, true); + $contentAfter = $phpcsFile->findNext(T_WHITESPACE, $closer + 1, null, true); if ($contentAfter !== false - && $tokens[$contentAfter]['line'] - $tokens[$scopeCloser]['line'] !== 2 + && $tokens[$contentAfter]['line'] - $tokens[$closer]['line'] !== 2 && $tokens[$contentAfter]['code'] !== T_CLOSE_CURLY_BRACKET ) { $error = 'Expected 1 blank line after method; %d found'; - $found = max($tokens[$contentAfter]['line'] - $tokens[$scopeCloser]['line'] - 1, 0); - $fix = $phpcsFile->addFixableError($error, $scopeCloser, '', [$found]); + $found = max($tokens[$contentAfter]['line'] - $tokens[$closer]['line'] - 1, 0); + $fix = $phpcsFile->addFixableError($error, $closer, '', [$found]); if ($fix) { if ($found) { $phpcsFile->fixer->beginChangeset(); - for ($i = $scopeCloser + 1; $i < $contentAfter - 1; $i++) { + for ($i = $closer + 1; $i < $contentAfter - 1; $i++) { $phpcsFile->fixer->replaceToken($i, ''); } $phpcsFile->fixer->endChangeset(); } else { - $phpcsFile->fixer->addNewline($scopeCloser); + $phpcsFile->fixer->addNewline($closer); } } } diff --git a/ZendCodingStandard/Tests/Methods/LineAfterUnitTest.1.inc b/ZendCodingStandard/Tests/Methods/LineAfterUnitTest.1.inc new file mode 100644 index 00000000..7f98da91 --- /dev/null +++ b/ZendCodingStandard/Tests/Methods/LineAfterUnitTest.1.inc @@ -0,0 +1,16 @@ + 1, + 8 => 1, + 13 => 1, + 14 => 2, + 15 => 1, + ]; + case 'LineAfterUnitTest.2.inc': + return [ + 7 => 1, + 10 => 1, + 15 => 1, + 20 => 1, + 21 => 2, + 22 => 1, + 24 => 1, + ]; + } + + return [ + 7 => 1, + 10 => 1, + 15 => 1, + 20 => 1, + 21 => 2, + 22 => 1, + 24 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 12c0ebb7f1c4d4a05dc1888c1cfa6752adecf5a8 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 30 Nov 2016 10:42:12 +0000 Subject: [PATCH 013/225] NamingConventions\ValidVariableName tests --- .../ValidVariableNameUnitTest.inc | 29 +++++++++++++++++++ .../ValidVariableNameUnitTest.php | 21 ++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 ZendCodingStandard/Tests/NamingConventions/ValidVariableNameUnitTest.inc create mode 100644 ZendCodingStandard/Tests/NamingConventions/ValidVariableNameUnitTest.php diff --git a/ZendCodingStandard/Tests/NamingConventions/ValidVariableNameUnitTest.inc b/ZendCodingStandard/Tests/NamingConventions/ValidVariableNameUnitTest.inc new file mode 100644 index 00000000..1fa89be9 --- /dev/null +++ b/ZendCodingStandard/Tests/NamingConventions/ValidVariableNameUnitTest.inc @@ -0,0 +1,29 @@ + 1, + 16 => 1, + 28 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 0748eb68a7c046183e75eb45003ad62751b61f4c Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 30 Nov 2016 13:08:11 +0000 Subject: [PATCH 014/225] PHP\TypeCasting tests --- .../Sniffs/PHP/TypeCastingSniff.php | 34 ++++++------- .../Tests/PHP/TypeCastingUnitTest.inc | 49 +++++++++++++++++++ .../Tests/PHP/TypeCastingUnitTest.inc.fixed | 49 +++++++++++++++++++ .../Tests/PHP/TypeCastingUnitTest.php | 43 ++++++++++++++++ 4 files changed, 155 insertions(+), 20 deletions(-) create mode 100644 ZendCodingStandard/Tests/PHP/TypeCastingUnitTest.inc create mode 100644 ZendCodingStandard/Tests/PHP/TypeCastingUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/PHP/TypeCastingUnitTest.php diff --git a/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php index d305ba35..a1f2faf6 100644 --- a/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php +++ b/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -2,6 +2,10 @@ /** * Copied from: * @see https://github.com/dereuromark/codesniffer-standards/blob/master/CakePHP/Sniffs/PHP/TypeCastingSniff.php + * + * Changes: + * - disallow (unset) cast + * - omit white chars in casting */ namespace ZendCodingStandard\Sniffs\PHP; @@ -58,9 +62,6 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) // Process !! casts if ($tokens[$stackPtr]['code'] == T_BOOLEAN_NOT) { $nextToken = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); - if (! $nextToken) { - return; - } if ($tokens[$nextToken]['code'] != T_BOOLEAN_NOT) { return; } @@ -77,39 +78,32 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) return; } + if ($tokens[$stackPtr]['code'] == T_UNSET_CAST) { + $phpcsFile->addError('(unset) casting is not allowed.', $stackPtr, 'UnsetCast'); + return; + } + // Only allow short forms if both short and long forms are possible $matching = [ '(boolean)' => '(bool)', '(integer)' => '(int)', ]; $content = $tokens[$stackPtr]['content']; - $key = strtolower($content); - if (isset($matching[$key])) { + $key = preg_replace('/\s/', '', strtolower($content)); + if (isset($matching[$key]) || $content !== $key) { $error = 'Please use %s instead of %s.'; + $expected = isset($matching[$key]) ? $matching[$key] : $key; $data = [ - $matching[$key], + $expected, $content, ]; $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed', $data); if ($fix) { - $phpcsFile->fixer->replaceToken($stackPtr, $matching[$key]); + $phpcsFile->fixer->replaceToken($stackPtr, $expected); } return; } - - if ($content !== $key) { - $error = 'Please use %s instead of %s.'; - $data = [ - $key, - $content, - ]; - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed', $data); - - if ($fix) { - $phpcsFile->fixer->replaceToken($stackPtr, $key); - } - } } } diff --git a/ZendCodingStandard/Tests/PHP/TypeCastingUnitTest.inc b/ZendCodingStandard/Tests/PHP/TypeCastingUnitTest.inc new file mode 100644 index 00000000..fc997a97 --- /dev/null +++ b/ZendCodingStandard/Tests/PHP/TypeCastingUnitTest.inc @@ -0,0 +1,49 @@ + 1, + 5 => 1, + 7 => 1, + 8 => 1, + 17 => 1, + 19 => 1, + 20 => 1, + 29 => 1, + 31 => 1, + 32 => 1, + 33 => 1, + 35 => 1, + 36 => 1, + 37 => 1, + 39 => 1, + 40 => 1, + 41 => 1, + 42 => 1, + 43 => 1, + 44 => 1, + 45 => 1, + 46 => 1, + 47 => 1, + 48 => 1, + 49 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 7bbd0a4ddd38b9558418fd2f054c5c4294220c30 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 30 Nov 2016 13:08:39 +0000 Subject: [PATCH 015/225] Added new rule: Squiz.WhiteSpace.CastSpacing.ContainsWhiteSpace --- ZendCodingStandard/ruleset.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ZendCodingStandard/ruleset.xml b/ZendCodingStandard/ruleset.xml index a1fa7b98..872ed2d6 100644 --- a/ZendCodingStandard/ruleset.xml +++ b/ZendCodingStandard/ruleset.xml @@ -40,6 +40,7 @@ Variable "%s" not allowed in double quoted string; use sprintf() instead. + @@ -59,6 +60,7 @@ + From 17ae5d4fa73e7ca4b86c3db89c02d2ba2433c83a Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 30 Nov 2016 13:33:55 +0000 Subject: [PATCH 016/225] New sniff: Strings\NoConcatenationAtTheEnd + tests --- .../Strings/NoConcatenationAtTheEndSniff.php | 37 +++++++++++++++++++ .../NoConcatenationAtTheEndUnitTest.inc | 10 +++++ .../NoConcatenationAtTheEndUnitTest.inc.fixed | 10 +++++ .../NoConcatenationAtTheEndUnitTest.php | 20 ++++++++++ 4 files changed, 77 insertions(+) create mode 100644 ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php create mode 100644 ZendCodingStandard/Tests/Strings/NoConcatenationAtTheEndUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Strings/NoConcatenationAtTheEndUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Strings/NoConcatenationAtTheEndUnitTest.php diff --git a/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php b/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php new file mode 100644 index 00000000..46de0c2c --- /dev/null +++ b/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php @@ -0,0 +1,37 @@ +getTokens(); + + $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); + + if ($tokens[$stackPtr]['line'] === $tokens[$next]['line']) { + return; + } + + $error = 'String concatenation character is not allowed at the end of the line.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + if ($tokens[$stackPtr - 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($stackPtr - 1, ''); + } + $phpcsFile->fixer->replaceToken($stackPtr, ''); + $phpcsFile->fixer->addContentBefore($next, '. '); + $phpcsFile->fixer->endChangeset(); + } + } +} diff --git a/ZendCodingStandard/Tests/Strings/NoConcatenationAtTheEndUnitTest.inc b/ZendCodingStandard/Tests/Strings/NoConcatenationAtTheEndUnitTest.inc new file mode 100644 index 00000000..a818100a --- /dev/null +++ b/ZendCodingStandard/Tests/Strings/NoConcatenationAtTheEndUnitTest.inc @@ -0,0 +1,10 @@ + 1, + 9 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 4a1b451dcacf8ef4b2e2c05c0c6ca0705557795f Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 30 Nov 2016 15:36:54 +0000 Subject: [PATCH 017/225] WhiteSpace\CommaSpacing sniff improvements + tests --- .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 107 +++++++----------- .../Tests/WhiteSpace/CommaSpacingUnitTest.inc | 49 ++++++++ .../WhiteSpace/CommaSpacingUnitTest.inc.fixed | 48 ++++++++ .../Tests/WhiteSpace/CommaSpacingUnitTest.php | 33 ++++++ 4 files changed, 173 insertions(+), 64 deletions(-) create mode 100644 ZendCodingStandard/Tests/WhiteSpace/CommaSpacingUnitTest.inc create mode 100644 ZendCodingStandard/Tests/WhiteSpace/CommaSpacingUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/WhiteSpace/CommaSpacingUnitTest.php diff --git a/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index eba4812d..9444e7f4 100644 --- a/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -2,10 +2,10 @@ /** * Check spaces before and after comma. * Before comma space is not allowed. - * After comma should be exactly only one comma. + * After comma should be exactly one comma. * There is allowed more than one space after comma only in when this is multidimensional array. * - * @todo: maybe we need fix part for multidimensional array, no it's checking for something like: + * @todo: maybe we need fix part for multidimensional array, now it's checking for something like: * [ * [1, 3423, 342, 4324], * [4432, 43, 4, 32], @@ -29,90 +29,69 @@ public function register() * @param PHP_CodeSniffer_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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); + // Check spaces before comma. $prevToken = $tokens[$stackPtr - 1]; - $prevType = $prevToken['code']; - if (isset(PHP_CodeSniffer_Tokens::$emptyTokens[$prevType])) { - $nonSpace = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr - 2, null, true); - $expected = $tokens[$nonSpace]['content'] . ','; - $found = $phpcsFile->getTokensAsString($nonSpace, $stackPtr - $nonSpace) . ','; - $error = 'Space found before comma; expected "%s" but found "%s"'; - $data = [ - $expected, - $found, - ]; - - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeComma', $data); + if ($prevToken['code'] === T_WHITESPACE) { + $error = 'Expected 0 spaces before comma; found %d'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeComma', [strlen($prevToken['content'])]); if ($fix) { - $phpcsFile->fixer->beginChangeset(); - for ($i = $stackPtr - 1; $i > $nonSpace; $i--) { - $phpcsFile->fixer->replaceToken($i, ''); - } - - $phpcsFile->fixer->endChangeset(); + $phpcsFile->fixer->replaceToken($stackPtr - 1, ''); } } $nextToken = $tokens[$stackPtr + 1]; - $nextType = $nextToken['code']; + if ($nextToken['code'] !== T_WHITESPACE) { + // There is no space after comma. - // There is no space after comma. - if ($nextType !== T_WHITESPACE) { $error = 'Expected 1 space after comma; found 0'; $fix = $phpcsFile->addFixableError($error, $stackPtr + 1, 'NoSpaceAfterComma'); if ($fix) { $phpcsFile->fixer->addContent($stackPtr, ' '); } - } elseif (strlen($nextToken['content']) !== 1) { + } elseif ($nextToken['content'] != ' ') { // There is more than one space after comma. - // Check if this is not before a comment at the end of the line - if ($tokens[$stackPtr + 2]['code'] !== T_COMMENT - && $tokens[$stackPtr + 3]['code'] !== T_WHITESPACE - && $tokens[$stackPtr + 3]['content'] !== $phpcsFile->eolChar - ) { - if ($tokens[$stackPtr + 2]['code'] === T_DOC_COMMENT_OPEN_TAG) { - $phpcsFile->addError( - 'Doc comment is not allowed here. Please use normal comment: /* ... */ or // ...', - $stackPtr + 2, - 'DocCommentNotAllowed' - ); - } else { - $openArray = $phpcsFile->findPrevious([T_OPEN_SHORT_ARRAY], $stackPtr); - $beforeOpening = $phpcsFile->findPrevious( - PHP_CodeSniffer_Tokens::$emptyTokens, - $openArray - 1, - null, - true - ); - $closeArray = $phpcsFile->findNext([T_CLOSE_SHORT_ARRAY], $stackPtr); - $afterClosing = $phpcsFile->findNext( - array_merge(PHP_CodeSniffer_Tokens::$emptyTokens, [T_COMMA]), - $closeArray + 1, - null, - true - ); + $nonSpace = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); + if ($tokens[$nonSpace]['line'] !== $tokens[$stackPtr]['line']) { + // Next non-space token is in new line, return. - if ($tokens[$openArray]['line'] !== $tokens[$closeArray]['line'] - || $tokens[$beforeOpening]['line'] === $tokens[$openArray]['line'] - || $tokens[$afterClosing]['line'] === $tokens[$closeArray]['line'] - ) { - $error = 'Expected 1 space after comma; found %d'; - $data = [ - strlen($nextToken['content']), - ]; - $fix = $phpcsFile->addFixableError($error, $stackPtr + 1, 'SpacingAfterComma', $data); + return; + } + + // Check if this is multidimensional array. + $openArray = $phpcsFile->findPrevious([T_OPEN_SHORT_ARRAY], $stackPtr); + $beforeOpening = $phpcsFile->findPrevious( + PHP_CodeSniffer_Tokens::$emptyTokens, + $openArray - 1, + null, + true + ); + $closeArray = $phpcsFile->findNext([T_CLOSE_SHORT_ARRAY], $stackPtr); + $afterClosing = $phpcsFile->findNext( + array_merge(PHP_CodeSniffer_Tokens::$emptyTokens, [T_COMMA]), + $closeArray + 1, + null, + true + ); + + if ($tokens[$openArray]['line'] !== $tokens[$closeArray]['line'] + || $tokens[$beforeOpening]['line'] === $tokens[$openArray]['line'] + || $tokens[$afterClosing]['line'] === $tokens[$closeArray]['line'] + ) { + $error = 'Expected 1 space after comma; found %d'; + $data = [ + strlen($nextToken['content']), + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr + 1, 'SpacingAfterComma', $data); - if ($fix) { - $phpcsFile->fixer->replaceToken($stackPtr + 1, ' '); - } - } + if ($fix) { + $phpcsFile->fixer->replaceToken($stackPtr + 1, ' '); } } } diff --git a/ZendCodingStandard/Tests/WhiteSpace/CommaSpacingUnitTest.inc b/ZendCodingStandard/Tests/WhiteSpace/CommaSpacingUnitTest.inc new file mode 100644 index 00000000..38ab6da8 --- /dev/null +++ b/ZendCodingStandard/Tests/WhiteSpace/CommaSpacingUnitTest.inc @@ -0,0 +1,49 @@ + 1, + 5 => 1, + 7 => 1, + 10 => 2, + 12 => 1, + 14 => 2, + 23 => 2, + 25 => 2, + 29 => 2, + 33 => 2, + 36 => 1, + 39 => 1, + 43 => 2, + 48 => 2, + 49 => 3, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From baa198958ea25a782c96dcd73544940505100596 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 30 Nov 2016 15:48:34 +0000 Subject: [PATCH 018/225] Updated rules: - added Squiz.Operators.ValidLogicalOperators - removed Squiz.WhiteSpace.CastSpacing.ContainsWhiteSpace - covered by ZendCodingStandard.PHP.TypeCasting --- ZendCodingStandard/ruleset.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZendCodingStandard/ruleset.xml b/ZendCodingStandard/ruleset.xml index 872ed2d6..0ddbcd49 100644 --- a/ZendCodingStandard/ruleset.xml +++ b/ZendCodingStandard/ruleset.xml @@ -35,12 +35,12 @@ + Variable "%s" not allowed in double quoted string; use sprintf() instead. - From 6746649fe7696183c0972b06e26d9b62ead6ac0b Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 30 Nov 2016 15:53:09 +0000 Subject: [PATCH 019/225] Added rule: Generic.NamingConventions.ConstructorName --- ZendCodingStandard/ruleset.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ZendCodingStandard/ruleset.xml b/ZendCodingStandard/ruleset.xml index 0ddbcd49..87035898 100644 --- a/ZendCodingStandard/ruleset.xml +++ b/ZendCodingStandard/ruleset.xml @@ -17,6 +17,7 @@ + @@ -26,6 +27,7 @@ + @@ -35,7 +37,6 @@ - Variable "%s" not allowed in double quoted string; use sprintf() instead. From 5314ee649d6841be7ecb1ad20d58e060b68a5e52 Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 2 Dec 2016 14:32:59 +0000 Subject: [PATCH 020/225] Added: PHP\LowerCaseKeyword Sniff + tests This sniffs cover 3 other sniffs (now excluded in ruleset): - Generic.PHP.LowerCaseKeyword - Squiz.ControlStructures.LowercaseDeclaration - Squiz.Functions.LowercaseFunctionKeywords --- .../Sniffs/PHP/LowerCaseKeywordSniff.php | 20 ++++++ .../Tests/PHP/LowerCaseKeywordUnitTest.inc | 66 +++++++++++++++++++ .../PHP/LowerCaseKeywordUnitTest.inc.fixed | 66 +++++++++++++++++++ .../Tests/PHP/LowerCaseKeywordUnitTest.php | 56 ++++++++++++++++ ZendCodingStandard/ruleset.xml | 7 +- 5 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php create mode 100644 ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.inc create mode 100644 ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.php diff --git a/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php b/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php new file mode 100644 index 00000000..9389cac5 --- /dev/null +++ b/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php @@ -0,0 +1,20 @@ + $b; + } + + FINAL PUBLIC FUNCTION finalMethod() + { + SWITCH (1) { + CASE 0: + RETURN FUNCTION () {}; + DEFAULT: + BREAK; + } + } +} diff --git a/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed b/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed new file mode 100644 index 00000000..e4787db2 --- /dev/null +++ b/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed @@ -0,0 +1,66 @@ + $b; + } + + final public function finalMethod() + { + switch (1) { + case 0: + return function () {}; + default: + break; + } + } +} diff --git a/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.php b/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.php new file mode 100644 index 00000000..55d62fc8 --- /dev/null +++ b/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.php @@ -0,0 +1,56 @@ + 1, + 5 => 1, + 7 => 2, + 8 => 1, + 9 => 1, + 11 => 1, + 13 => 3, + 15 => 1, + 16 => 1, + 18 => 1, + 19 => 1, + 21 => 3, + 22 => 4, + 23 => 1, + 27 => 3, + 29 => 3, + 31 => 1, + 34 => 1, + 35 => 1, + 37 => 1, + 38 => 1, + 41 => 1, + 42 => 1, + 43 => 1, + 44 => 1, + 45 => 1, + 46 => 1, + 47 => 2, + 50 => 1, + 51 => 2, + 53 => 1, + 54 => 1, + 57 => 3, + 59 => 1, + 60 => 1, + 61 => 2, + 62 => 1, + 63 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} diff --git a/ZendCodingStandard/ruleset.xml b/ZendCodingStandard/ruleset.xml index 87035898..89e0d89b 100644 --- a/ZendCodingStandard/ruleset.xml +++ b/ZendCodingStandard/ruleset.xml @@ -7,7 +7,12 @@ - + + + + + + From c04a5feff18ec9f2e74380693620e5a18351f84d Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 2 Dec 2016 14:34:01 +0000 Subject: [PATCH 021/225] Tests fix - correct detecting testing files --- ZendCodingStandard/Tests/TestCase.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ZendCodingStandard/Tests/TestCase.php b/ZendCodingStandard/Tests/TestCase.php index 60989760..583076be 100644 --- a/ZendCodingStandard/Tests/TestCase.php +++ b/ZendCodingStandard/Tests/TestCase.php @@ -39,7 +39,10 @@ protected function getTestFiles($testFileBase) } $path = $file->getPathname(); - if ($path !== $testFileBase . 'php' && substr($path, -5) !== 'fixed') { + if (substr($path, 0, strlen($testFileBase)) === $testFileBase + && $path !== $testFileBase . 'php' + && substr($path, -5) !== 'fixed' + ) { $testFiles[] = $path; } } From 8ab47c4733395f31f9163bbc45d57f01434da2c7 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 4 Dec 2016 20:17:13 +0000 Subject: [PATCH 022/225] Commenting\DocComment sniff fixes, added PHPDocs, test fix --- .../Sniffs/Commenting/DocCommentSniff.php | 110 +++++++++++++++--- .../Tests/Commenting/DocCommentUnitTest.3.inc | 2 +- 2 files changed, 96 insertions(+), 16 deletions(-) diff --git a/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index 610e981d..a1b83d4d 100644 --- a/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -6,11 +6,19 @@ class DocCommentSniff implements PHP_CodeSniffer_Sniff { + /** + * @return array + */ public function register() { return [T_DOC_COMMENT_OPEN_TAG]; } + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @return void + */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); @@ -39,6 +47,14 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $this->checkBlankLinesInComment($phpcsFile, $commentStart, $commentEnd); } + /** + * Checks if doc comment is empty. + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $commentStart + * @param int $commentEnd + * @return bool + */ private function checkIfEmpty(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) { $tokens = $phpcsFile->getTokens(); @@ -85,7 +101,7 @@ private function checkIfEmpty(PHP_CodeSniffer_File $phpcsFile, $commentStart, $c ) { $phpcsFile->fixer->replaceToken($commentStart - 1, ''); } elseif ($tokens[$commentStart - 1]['code'] === T_OPEN_TAG - && ($next = $phpcsFile->findNext([T_WHITESPACE], $commentEnd + 1, null, true)) + && ($next = $phpcsFile->findNext(T_WHITESPACE, $commentEnd + 1, null, true)) && $tokens[$next]['line'] > $tokens[$commentEnd]['line'] + 1 ) { $phpcsFile->fixer->replaceToken($commentEnd + 1, ''); @@ -96,22 +112,31 @@ private function checkIfEmpty(PHP_CodeSniffer_File $phpcsFile, $commentStart, $c return true; } + /** + * Checks if there is no any other content before doc comment opening tag, + * and if there is blank line before doc comment (for multiline doc comment). + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $commentStart + * @return void + */ private function checkBeforeOpen(PHP_CodeSniffer_File $phpcsFile, $commentStart) { $tokens = $phpcsFile->getTokens(); - $previous = $phpcsFile->findPrevious([T_WHITESPACE], $commentStart - 1, null, true); + $previous = $phpcsFile->findPrevious(T_WHITESPACE, $commentStart - 1, null, true); if ($tokens[$previous]['line'] === $tokens[$commentStart]['line']) { $error = 'The open comment tag must be the only content on the line.'; $fix = $phpcsFile->addFixableError($error, $commentStart); if ($fix) { - $nonEmpty = $phpcsFile->findPrevious([T_WHITESPACE], $commentStart - 1, null, true); + $nonEmpty = $phpcsFile->findPrevious(T_WHITESPACE, $commentStart - 1, null, true); $phpcsFile->fixer->beginChangeset(); $prev = $commentStart; - while ($prev = $phpcsFile->findPrevious([T_WHITESPACE], $prev - 1, $nonEmpty)) { + while ($prev = $phpcsFile->findPrevious(T_WHITESPACE, $prev - 1, $nonEmpty)) { $phpcsFile->fixer->replaceToken($prev, ''); } + $phpcsFile->fixer->replaceToken($nonEmpty, trim($tokens[$nonEmpty]['content'])); $phpcsFile->fixer->addNewline($commentStart - 1); $phpcsFile->fixer->endChangeset(); } @@ -123,20 +148,23 @@ private function checkBeforeOpen(PHP_CodeSniffer_File $phpcsFile, $commentStart) $fix = $phpcsFile->addFixableError($error, $commentStart); if ($fix) { -// if ($tokens[$commentStart - 1]['code'] === T_WHITESPACE) { - $phpcsFile->fixer->addNewlineBefore($commentStart - 1); -// } else { -// $phpcsFile->fixer->addNewlineBefore($commentStart); -// } + $phpcsFile->fixer->addNewlineBefore($commentStart); } } } + /** + * Checks if there is no any other content after doc comment opening tag (for multiline doc comment). + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $commentStart + * @return void + */ private function checkAfterOpen(PHP_CodeSniffer_File $phpcsFile, $commentStart) { $tokens = $phpcsFile->getTokens(); - $next = $phpcsFile->findNext([T_DOC_COMMENT_WHITESPACE], $commentStart + 1, null, true); + $next = $phpcsFile->findNext(T_DOC_COMMENT_WHITESPACE, $commentStart + 1, null, true); if ($tokens[$next]['line'] === $tokens[$commentStart]['line']) { $error = 'The open comment tag must be the only content on the line.'; $fix = $phpcsFile->addFixableError($error, $commentStart); @@ -164,11 +192,18 @@ private function checkAfterOpen(PHP_CodeSniffer_File $phpcsFile, $commentStart) } } + /** + * Checks if there is no any other content before doc comment closing tag (for multiline doc comment). + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $commentEnd + * @return void + */ private function checkBeforeClose(PHP_CodeSniffer_File $phpcsFile, $commentEnd) { $tokens = $phpcsFile->getTokens(); - $previous = $phpcsFile->findPrevious([T_DOC_COMMENT_WHITESPACE], $commentEnd - 1, null, true); + $previous = $phpcsFile->findPrevious(T_DOC_COMMENT_WHITESPACE, $commentEnd - 1, null, true); if ($tokens[$previous]['line'] === $tokens[$commentEnd]['line']) { $error = 'The close comment tag must be the only content on the line.'; $fix = $phpcsFile->addFixableError($error, $commentEnd); @@ -185,6 +220,14 @@ private function checkBeforeClose(PHP_CodeSniffer_File $phpcsFile, $commentEnd) } } + /** + * Checks if there is no any other content after doc comment closing tag (for multiline doc comment). + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $commentStart + * @param int $commentEnd + * @return void + */ private function checkAfterClose(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) { $tokens = $phpcsFile->getTokens(); @@ -194,7 +237,7 @@ private function checkAfterClose(PHP_CodeSniffer_File $phpcsFile, $commentStart, T_USE, ]; - $next = $phpcsFile->findNext([T_WHITESPACE], $commentEnd + 1, null, true); + $next = $phpcsFile->findNext(T_WHITESPACE, $commentEnd + 1, null, true); if (! $next) { $error = 'Doc comment is not allowed at the end of the file.'; @@ -236,6 +279,15 @@ private function checkAfterClose(PHP_CodeSniffer_File $phpcsFile, $commentStart, } } + /** + * Checks if there is exactly one space after doc comment opening tag, + * and exactly one space before closing tag (for single line doc comment). + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $commentStart + * @param int $commentEnd + * @return void + */ private function checkSpacesInOneLineComment(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) { $tokens = $phpcsFile->getTokens(); @@ -273,6 +325,17 @@ private function checkSpacesInOneLineComment(PHP_CodeSniffer_File $phpcsFile, $c } } + /** + * Checks if there is one space after star in multiline doc comment. + * More than one space is allowed, unless the line contains tag. + * + * TODO: needs to check with doctrine annotations + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $commentStart + * @param int $commentEnd + * @return void + */ private function checkSpacesAfterStar(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) { $tokens = $phpcsFile->getTokens(); @@ -307,6 +370,15 @@ private function checkSpacesAfterStar(PHP_CodeSniffer_File $phpcsFile, $commentS } } + /** + * Doc comment cannot have empty line on the beginning of the comment, at the end of the comment, + * and there is allowed only one empty line between two comment sections. + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $commentStart + * @param int $commentEnd + * @return void + */ private function checkBlankLinesInComment(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) { $tokens = $phpcsFile->getTokens(); @@ -362,7 +434,7 @@ private function checkBlankLinesInComment(PHP_CodeSniffer_File $phpcsFile, $comm if ($tokens[$next]['line'] > $tokens[$from]['line'] + 2) { $error = 'More than one blank line between parts of doc block.'; $i = 0; - while ($token = $phpcsFile->findNext([T_DOC_COMMENT_STAR], $from + 1, $next - 2)) { + while ($token = $phpcsFile->findNext(T_DOC_COMMENT_STAR, $from + 1, $next - 2)) { if ($i++ > 0) { $fix = $phpcsFile->addFixableError($error, $token); @@ -382,6 +454,14 @@ private function checkBlankLinesInComment(PHP_CodeSniffer_File $phpcsFile, $comm } } + /** + * Checks indents of the comment (opening tag, lines with star, closing tag). + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $commentStart + * @param int $commentEnd + * @return void + */ private function checkCommentIndents(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) { $tokens = $phpcsFile->getTokens(); @@ -391,7 +471,7 @@ private function checkCommentIndents(PHP_CodeSniffer_File $phpcsFile, $commentSt T_USE, ]; - $next = $phpcsFile->findNext([T_WHITESPACE], $commentEnd + 1, null, true); + $next = $phpcsFile->findNext(T_WHITESPACE, $commentEnd + 1, null, true); // There is something exactly in the next line. if ($next && $tokens[$next]['line'] === $tokens[$commentEnd]['line'] + 1) { @@ -413,7 +493,7 @@ private function checkCommentIndents(PHP_CodeSniffer_File $phpcsFile, $commentSt } // The open tag is alone in the line. - $previous = $phpcsFile->findPrevious([T_WHITESPACE], $commentStart - 1, null, true); + $previous = $phpcsFile->findPrevious(T_WHITESPACE, $commentStart - 1, null, true); if ($tokens[$previous]['line'] < $tokens[$commentStart]['line']) { // Check if comment starts with the same indent. $spaces = $tokens[$commentStart - 1]; diff --git a/ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.3.inc b/ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.3.inc index 1ce43375..71252c18 100644 --- a/ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.3.inc +++ b/ZendCodingStandard/Tests/Commenting/DocCommentUnitTest.3.inc @@ -1,4 +1,4 @@ - Date: Sun, 4 Dec 2016 20:18:07 +0000 Subject: [PATCH 023/225] Added PHP\CorrectClassNameCase sniff + tests --- .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 353 ++++++++++++++++++ .../PHP/CorrectClassNameCaseUnitTest.1.inc | 11 + .../CorrectClassNameCaseUnitTest.1.inc.fixed | 11 + .../PHP/CorrectClassNameCaseUnitTest.inc | 55 +++ .../CorrectClassNameCaseUnitTest.inc.fixed | 55 +++ .../PHP/CorrectClassNameCaseUnitTest.php | 48 +++ 6 files changed, 533 insertions(+) create mode 100644 ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php create mode 100644 ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.1.inc create mode 100644 ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.1.inc.fixed create mode 100644 ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.inc create mode 100644 ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.php diff --git a/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php new file mode 100644 index 00000000..95ff652c --- /dev/null +++ b/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -0,0 +1,353 @@ +declaredClasses = array_merge( + get_declared_classes(), + get_declared_interfaces(), + get_declared_traits() + ); + } + + /** + * @return array + */ + public function register() + { + return [ + T_NEW, + T_USE, + T_DOUBLE_COLON, + T_IMPLEMENTS, + T_EXTENDS, + ]; + } + + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @return void + */ + public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['code']) { + case T_DOUBLE_COLON: + $this->checkDoubleColon($phpcsFile, $stackPtr); + return; + case T_NEW: + $this->checkNew($phpcsFile, $stackPtr); + return; + case T_USE: + $this->checkUse($phpcsFile, $stackPtr); + return; + } + + $this->checkExtendsAndImplements($phpcsFile, $stackPtr); + } + + /** + * Checks statement before double colon - "ClassName::". + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @return void + */ + private function checkDoubleColon(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); + + // When "static::", "self::", "parent::" or "$var::", skip. + if ($tokens[$prevToken]['code'] === T_STATIC + || $tokens[$prevToken]['code'] === T_SELF + || $tokens[$prevToken]['code'] === T_PARENT + || $tokens[$prevToken]['code'] === T_VARIABLE + ) { + return; + } + + $start = $phpcsFile->findPrevious( + [T_NS_SEPARATOR, T_STRING], + $prevToken - 1, + null, + true + ); + + $this->checkClass($phpcsFile, $start + 1, $prevToken + 1);//$prevToken - $start); + } + + /** + * Checks "new ClassName" statements. + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @return void + */ + private function checkNew(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // todo: check next character after new - should be exactly one space + + $nextToken = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); + + // When "new static", "new self" or "new $var", skip. + if ($tokens[$nextToken]['code'] === T_STATIC + || $tokens[$nextToken]['code'] === T_SELF + || $tokens[$nextToken]['code'] === T_VARIABLE + ) { + return; + } + + $end = $phpcsFile->findNext( + [T_NS_SEPARATOR, T_STRING], + $nextToken + 1, + null, + true + ); + + $this->checkClass($phpcsFile, $nextToken, $end); + } + + /** + * Checks "use" statements - global and traits. + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @return void + */ + private function checkUse(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextToken = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); + + $end = $phpcsFile->findNext( + [T_NS_SEPARATOR, T_STRING], + $nextToken + 1, + null, + true + ); + + // Global use statements. + if (empty($tokens[$stackPtr]['conditions'])) { + $this->checkClass($phpcsFile, $nextToken, $end, true); + return; + } + + // Traits. + $this->checkClass($phpcsFile, $nextToken, $end); + } + + /** + * Checks "extends" and "implements" classes/interfaces. + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @return void + */ + private function checkExtendsAndImplements(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $search = $stackPtr; + while ($nextToken = $phpcsFile->findNext([T_WHITESPACE, T_COMMA], $search + 1, null, true)) { + if ($tokens[$nextToken]['code'] !== T_NS_SEPARATOR + && $tokens[$nextToken]['code'] !== T_STRING + ) { + break; + } + + $end = $phpcsFile->findNext( + [T_NS_SEPARATOR, T_STRING], + $nextToken + 1, + null, + true + ); + + $this->checkClass($phpcsFile, $nextToken, $end); + + $search = $end; + } + } + + /** + * Checks if class is used correctly. + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $start + * @param int $end + * @param bool $isGlobalUse + * @return void + */ + private function checkClass(PHP_CodeSniffer_File $phpcsFile, $start, $end, $isGlobalUse = false) + { + $class = trim($phpcsFile->getTokensAsString($start, $end - $start)); + if ($class[0] == '\\') { + $result = $this->hasDifferentCase(ltrim($class, '\\')); + if ($result) { + $this->error($phpcsFile, $start, $end, '\\' . $result, $class); + } + + return; + } + + if (! $isGlobalUse) { + $imports = $this->getGlobalUses($phpcsFile); + + // Check if class is imported. + if (isset($imports[strtolower($class)])) { + if ($imports[strtolower($class)]['alias'] !== $class) { + $this->error($phpcsFile, $start, $end, $imports[strtolower($class)]['alias'], $class); + } + } else { + // Class from the same namespace. + $namespace = $this->getNamespace($phpcsFile, $start); + $fullClassName = ltrim($namespace . '\\' . $class, '\\'); + + $result = $this->hasDifferentCase(ltrim($fullClassName, '\\')); + if ($result) { + $this->error($phpcsFile, $start, $end, ltrim(substr($result, strlen($namespace)), '\\'), $class); + } + } + } else { + // Global use statement. + $result = $this->hasDifferentCase($class); + if ($result) { + $this->error($phpcsFile, $start, $end, $result, $class); + } + } + } + + /** + * Reports new fixable error. + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $start + * @param int $end + * @param string $expected + * @param string $actual + * @return void + */ + private function error(PHP_CodeSniffer_File $phpcsFile, $start, $end, $expected, $actual) + { + $error = 'Invalid class name case: expected %s; found %s'; + $data = [ + $expected, + $actual, + ]; + $fix = $phpcsFile->addFixableError($error, $start + 1, '', $data); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $start; $i < $end - 1; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->replaceToken($end - 1, $expected); + $phpcsFile->fixer->endChangeset(); + } + } + + /** + * Returns array of imported classes. Key is lowercase name, and value is FQCN. + * + * @param PHP_CodeSniffer_File $phpcsFile + * @return array + */ + private function getGlobalUses(PHP_CodeSniffer_File $phpcsFile) + { + $tokens = $phpcsFile->getTokens(); + + $imports = []; + + $use = 0; + while ($use = $phpcsFile->findNext(T_USE, $use + 1)) { + if (! empty($tokens[$use]['conditions'])) { + continue; + } + + $nextToken = $phpcsFile->findNext(T_WHITESPACE, $use + 1, null, true); + + $end = $phpcsFile->findNext( + [T_NS_SEPARATOR, T_STRING], + $nextToken + 1, + null, + true + ); + + $class = trim($phpcsFile->getTokensAsString($nextToken, $end - $nextToken)); + + $endOfStatement = $phpcsFile->findEndOfStatement($use); + if ($aliasStart = $phpcsFile->findNext([T_WHITESPACE, T_AS], $end + 1, $endOfStatement, true)) { + $alias = trim($phpcsFile->getTokensAsString($aliasStart, $endOfStatement - $aliasStart)); + } else { + if (strrchr($class, '\\') !== false) { + $alias = substr(strrchr($class, '\\'), 1); + } else { + $alias = $class; + } + } + + $imports[strtolower($alias)] = ['alias' => $alias, 'class' => $class]; + } + + return $imports; + } + + /** + * Checks if class is defined and has different case - then returns class name + * with correct case. Otherwise returns false. + * + * @param string $class + * @return false|string + */ + private function hasDifferentCase($class) + { + $index = array_search(strtolower($class), array_map('strtolower', $this->declaredClasses)); + + if ($index === false) { + // Not defined? + return false; + } + + if ($this->declaredClasses[$index] === $class) { + // Exactly the same. + return false; + } + + return $this->declaredClasses[$index]; + } + + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @return string + */ + private function getNamespace(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + if ($nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr - 1)) { + $nsEnd = $phpcsFile->findNext([T_NS_SEPARATOR, T_STRING, T_WHITESPACE], $nsStart + 1, null, true); + return trim($phpcsFile->getTokensAsString($nsStart + 1, $nsEnd - $nsStart - 1)); + } + + return ''; + } +} diff --git a/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.1.inc b/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.1.inc new file mode 100644 index 00000000..f0833a44 --- /dev/null +++ b/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.1.inc @@ -0,0 +1,11 @@ + 1, + 5 => 1, + 8 => 1, + 9 => 1, + 11 => 1, + ]; + } + + return [ + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 15 => 1, + 17 => 1, + // 18 => 0, + 21 => 1, + // 25 => 0, + 26 => 1, + 27 => 1, + 28 => 1, + 31 => 1, + 33 => 1, + // 38 => 0, + 40 => 1, + 43 => 1, + 48 => 1, + 53 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 45776da40e1e383aba4ea2bff60fce710c8dbac3 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 4 Dec 2016 22:58:52 +0000 Subject: [PATCH 024/225] Fix PHP\CorrectClassNameCase - skip "use" inside closures. --- .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 8 ++++++++ .../Tests/PHP/CorrectClassNameCaseUnitTest.inc | 4 +++- .../Tests/PHP/CorrectClassNameCaseUnitTest.inc.fixed | 4 +++- .../Tests/PHP/CorrectClassNameCaseUnitTest.php | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index 95ff652c..3433c3b1 100644 --- a/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -7,6 +7,8 @@ /** * TODO: Better results for this sniff we will have if the parsed class is imported. * We can "include" the file on process, but probably it is not the best solution. + * + * TODO: Checks T_STRING (classes in doc comments?) */ class CorrectClassNameCaseSniff implements PHP_CodeSniffer_Sniff { @@ -138,6 +140,12 @@ private function checkUse(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); + // Ignore USE keywords inside closures. + $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + return; + } + $nextToken = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); $end = $phpcsFile->findNext( diff --git a/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.inc b/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.inc index 506f1d70..b0ba35ac 100644 --- a/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.inc +++ b/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.inc @@ -48,8 +48,10 @@ class MyClass throw new Invalidargumentexception; } - public function fromNamespace() + public function fromNamespace($foo) { + $closure = function () use ($foo) {}; + return new CorrectclassnamecaseUnitTest(); } } diff --git a/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.inc.fixed b/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.inc.fixed index 9ffd2932..ef6ba736 100644 --- a/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.inc.fixed +++ b/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.inc.fixed @@ -48,8 +48,10 @@ class MyClass throw new InvalidArgumentException; } - public function fromNamespace() + public function fromNamespace($foo) { + $closure = function () use ($foo) {}; + return new CorrectClassNameCaseUnitTest(); } } diff --git a/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.php b/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.php index 13e3f7f3..803b16c4 100644 --- a/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.php +++ b/ZendCodingStandard/Tests/PHP/CorrectClassNameCaseUnitTest.php @@ -37,7 +37,7 @@ public function getErrorList($testFile = '') 40 => 1, 43 => 1, 48 => 1, - 53 => 1, + 55 => 1, ]; } From dc2afe86b7ea6814867583ce0ad4005bc5c648db Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Dec 2016 14:29:45 +0000 Subject: [PATCH 025/225] Fix for UnusedUseStatement sniff Namespace is imported (`use MyNamespace`) and class is used only in doc-comment (`/** @var MyNamespace\MyType $var */`) --- ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php | 2 +- .../Tests/Classes/UnusedUseStatementUnitTest.inc | 4 ++++ .../Tests/Classes/UnusedUseStatementUnitTest.inc.fixed | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php index 6d709b73..1237e8d6 100644 --- a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php +++ b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php @@ -128,7 +128,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) && strtolower($tokens[$classUsed]['content']) === $lowerClassName) || ($tokens[$classUsed]['code'] == T_DOC_COMMENT_STRING && preg_match( - '/(\s|\||^)' . preg_quote($lowerClassName) . '(\s|\||$|\[\])/i', + '/(\s|\||^)' . preg_quote($lowerClassName) . '(\s|\||\\\\|$|\[\])/i', $tokens[$classUsed]['content'] )) || ($tokens[$classUsed]['code'] == T_DOC_COMMENT_TAG diff --git a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc index fb0b412d..1bfbffae 100644 --- a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc +++ b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc @@ -22,6 +22,7 @@ use FooBar\Unused5; use Used10; use Used11; use FooBar\Used12 as AliasUsed12; +use FooBar\Used13; /** * @Used10 @@ -66,5 +67,8 @@ class Foo // @var Unused5 $x $x = $y; + + /** @var Used13\MyType $x */ + $x = $y; } } diff --git a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed index 851c499f..52686ba8 100644 --- a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed +++ b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed @@ -16,6 +16,7 @@ use Bar\Baz\Used9 as AliasUsed9; use Used10; use Used11; use FooBar\Used12 as AliasUsed12; +use FooBar\Used13; /** * @Used10 @@ -60,5 +61,8 @@ class Foo // @var Unused5 $x $x = $y; + + /** @var Used13\MyType $x */ + $x = $y; } } From 0b14160d9eaeaf45368d23fcdb17cb06a978bb95 Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Dec 2016 16:18:50 +0000 Subject: [PATCH 026/225] Added WhiteSpace\NoBlankLineAtStart sniff + tests Disallow blank line(s) at start of: - class - closure - function - interface - trait --- .../WhiteSpace/NoBlankLineAtStartSniff.php | 57 +++++++++++++++++++ .../WhiteSpace/NoBlankLineAtStartUnitTest.inc | 57 +++++++++++++++++++ .../NoBlankLineAtStartUnitTest.inc.fixed | 47 +++++++++++++++ .../WhiteSpace/NoBlankLineAtStartUnitTest.php | 28 +++++++++ 4 files changed, 189 insertions(+) create mode 100644 ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php create mode 100644 ZendCodingStandard/Tests/WhiteSpace/NoBlankLineAtStartUnitTest.inc create mode 100644 ZendCodingStandard/Tests/WhiteSpace/NoBlankLineAtStartUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/WhiteSpace/NoBlankLineAtStartUnitTest.php diff --git a/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php b/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php new file mode 100644 index 00000000..9446cf0a --- /dev/null +++ b/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php @@ -0,0 +1,57 @@ +getTokens(); + $token = $tokens[$stackPtr]; + + // Skip function without body. + if (! isset($token['scope_opener'])) { + return; + } + + $scopeOpener = $tokens[$stackPtr]['scope_opener']; + $firstContent = $phpcsFile->findNext(T_WHITESPACE, $scopeOpener + 1, null, true); + + if ($tokens[$firstContent]['line'] > $tokens[$scopeOpener]['line'] + 1) { + $error = sprintf('Blank line found at start of %s', $token['content']); + $fix = $phpcsFile->addFixableError($error, $scopeOpener + 1); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $i = $scopeOpener + 1; + while ($tokens[$i]['line'] !== $tokens[$firstContent]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + ++$i; + } + $phpcsFile->fixer->addNewline($scopeOpener); + $phpcsFile->fixer->endChangeset(); + } + } + } +} diff --git a/ZendCodingStandard/Tests/WhiteSpace/NoBlankLineAtStartUnitTest.inc b/ZendCodingStandard/Tests/WhiteSpace/NoBlankLineAtStartUnitTest.inc new file mode 100644 index 00000000..4da5d7b6 --- /dev/null +++ b/ZendCodingStandard/Tests/WhiteSpace/NoBlankLineAtStartUnitTest.inc @@ -0,0 +1,57 @@ + 1, + 9 => 1, + 17 => 1, + 19 => 1, + 30 => 1, + 36 => 1, + 42 => 1, + 45 => 1, + 47 => 1, + 54 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 8bd9b9d11d48c5b32e3bcf0046c0c5698dec4763 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 8 Dec 2016 14:47:09 +0000 Subject: [PATCH 027/225] Added Array\Format sniff + tests --- .../Sniffs/Arrays/FormatSniff.php | 221 ++++++++++++++++++ .../Tests/Arrays/FormatUnitTest.inc | 77 ++++++ .../Tests/Arrays/FormatUnitTest.inc.fixed | 88 +++++++ .../Tests/Arrays/FormatUnitTest.php | 49 ++++ 4 files changed, 435 insertions(+) create mode 100644 ZendCodingStandard/Sniffs/Arrays/FormatSniff.php create mode 100644 ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Arrays/FormatUnitTest.php diff --git a/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php new file mode 100644 index 00000000..a50530a2 --- /dev/null +++ b/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -0,0 +1,221 @@ +getTokens(); + $arrayToken = $tokens[$stackPtr]; + + $bracketOpener = $arrayToken['bracket_opener']; + $bracketCloser = $arrayToken['bracket_closer']; + + if ($tokens[$bracketOpener]['line'] !== $tokens[$bracketCloser]['line']) { + $this->multiLineArray($phpcsFile, $stackPtr); + return; + } + + $this->singleLineArray($phpcsFile, $stackPtr); + } + + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @return void + */ + private function multiLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $arrayToken = $tokens[$stackPtr]; + + $bracketOpener = $arrayToken['bracket_opener']; + $bracketCloser = $arrayToken['bracket_closer']; + + $firstContent = $phpcsFile->findNext(T_WHITESPACE, $bracketOpener + 1, null, true); + if ($tokens[$firstContent]['code'] === T_CLOSE_SHORT_ARRAY) { + $error = 'Empty array must be in one line.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr); + + if ($fix) { + $phpcsFile->fixer->replaceToken($bracketOpener + 1, ''); + } + + return; + } + + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $bracketCloser - 1, null, true); + if ($tokens[$bracketCloser]['line'] > $tokens[$lastContent]['line'] + 1) { + $error = 'Blank line found at the end of array'; + $fix = $phpcsFile->addFixableError($error, $bracketCloser - 1); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $i = $lastContent + 1; + while ($tokens[$i]['line'] !== $tokens[$bracketCloser]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + ++$i; + } + $phpcsFile->fixer->addNewlineBefore($bracketCloser); + $phpcsFile->fixer->endChangeset(); + } + } + + $first = $phpcsFile->findFirstOnLine([], $bracketOpener, true); + $indent = $tokens[$first]['code'] === T_WHITESPACE + ? strlen($tokens[$first]['content']) + : 0; + + $previousLine = $tokens[$bracketOpener]['line']; + $next = $bracketOpener; + while ($next = $phpcsFile->findNext(T_WHITESPACE, $next + 1, $bracketCloser, true)) { + if ($previousLine === $tokens[$next]['line']) { + if ($tokens[$next]['code'] !== T_COMMENT) { + $error = 'There must be one array element per line.'; + $fix = $phpcsFile->addFixableError($error, $next); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + if ($tokens[$next - 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($next - 1, ''); + } + $phpcsFile->fixer->addNewlineBefore($next); + $phpcsFile->fixer->endChangeset(); + } + } + } else { + if ($previousLine < $tokens[$next]['line'] - 1) { + $firstOnLine = $phpcsFile->findFirstOnLine([], $next, true); + + $fix = $phpcsFile->addFixableError('Empty line is not allowed here.', $firstOnLine - 1); + + if ($fix) { + $phpcsFile->fixer->replaceToken($firstOnLine - 1, ''); + } + } + + $expected = $indent + $this->indent; + + // Checks array element indent. + if ($firstOnLine = $phpcsFile->findFirstOnLine(T_WHITESPACE, $next)) { + $found = strlen($tokens[$firstOnLine]['content']); + if ($found !== $expected) { + $error = 'Invalid array element indent - expected %d spaces; %d found'; + $data = [ + $expected, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $firstOnLine, 'ElementIndent', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($firstOnLine, str_repeat(' ', $expected)); + } + } + } else { + $error = 'Invalid array element indent - expected %d spaces; 0 found'; + $fix = $phpcsFile->addFixableError($error, $next, 'ElementIndent', [$expected]); + + if ($fix) { + $phpcsFile->fixer->addContentBefore($next, str_repeat(' ', $expected)); + } + } + } + + if ($tokens[$next]['code'] === T_COMMENT + && (substr($tokens[$next]['content'], 0, 2) === '//' + || substr($tokens[$next]['content'], 0, 1) === '#') + ) { + $end = $next; + } else { + $end = $phpcsFile->findEndOfStatement($next); + if ($tokens[$end]['code'] === T_DOUBLE_ARROW) { + $end = $phpcsFile->findEndOfStatement($end); + } + } + + $previousLine = $tokens[$end]['line']; + $next = $end; + } + + if ($first = $phpcsFile->findFirstOnLine([], $bracketCloser, true)) { + if ($first < $bracketCloser - 1) { + $error = 'Array closing bracket should be in new line.'; + $fix = $phpcsFile->addFixableError($error, $bracketCloser); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + if ($indent > 0) { + $phpcsFile->fixer->addContentBefore($bracketCloser, str_repeat(' ', $indent)); + } + $phpcsFile->fixer->addNewlineBefore($bracketCloser); + $phpcsFile->fixer->endChangeset(); + } + } + } + } + + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @return void + */ + private function singleLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $arrayToken = $tokens[$stackPtr]; + + $bracketOpener = $arrayToken['bracket_opener']; + $bracketCloser = $arrayToken['bracket_closer']; + + // Single-line array - spaces before first element + if ($tokens[$bracketOpener + 1]['code'] === T_WHITESPACE) { + $error = sprintf( + 'Expected 0 spaces after array bracket opener; %d found', + strlen($tokens[$bracketOpener + 1]['content']) + ); + + $fix = $phpcsFile->addFixableError($error, $bracketOpener + 1); + + if ($fix) { + $phpcsFile->fixer->replaceToken($bracketOpener + 1, ''); + } + } + + // Single-line array - spaces before last element + if ($tokens[$bracketCloser - 1]['code'] === T_WHITESPACE) { + $error = sprintf( + 'Expected 0 spaces before array bracket closer; %d found', + strlen($tokens[$bracketCloser - 1]['content']) + ); + + $fix = $phpcsFile->addFixableError($error, $bracketCloser - 1); + + if ($fix) { + $phpcsFile->fixer->replaceToken($bracketCloser - 1, ''); + } + } + } +} diff --git a/ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc b/ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc new file mode 100644 index 00000000..12c255fd --- /dev/null +++ b/ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc @@ -0,0 +1,77 @@ + 1, 2 => 1, + 3 => 2, 4 => 3, + 5 => 5, +]; + +$arr = [ + + 'elem', 'elem', + +]; diff --git a/ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc.fixed b/ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc.fixed new file mode 100644 index 00000000..9626f599 --- /dev/null +++ b/ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc.fixed @@ -0,0 +1,88 @@ + 1, + 2 => 1, + 3 => 2, + 4 => 3, + 5 => 5, +]; + +$arr = [ + 'elem', + 'elem', +]; diff --git a/ZendCodingStandard/Tests/Arrays/FormatUnitTest.php b/ZendCodingStandard/Tests/Arrays/FormatUnitTest.php new file mode 100644 index 00000000..f13d3ff7 --- /dev/null +++ b/ZendCodingStandard/Tests/Arrays/FormatUnitTest.php @@ -0,0 +1,49 @@ + 2, + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 11 => 1, + 12 => 1, + 14 => 2, + 15 => 1, + 16 => 2, + 19 => 1, + 20 => 1, + 22 => 1, + 25 => 1, + 31 => 3, + 33 => 1, + 38 => 2, + 39 => 1, + 40 => 1, + 47 => 2, + 49 => 1, + 53 => 2, + 55 => 1, + 56 => 2, + 62 => 2, + 63 => 1, + 68 => 2, + 69 => 2, + 74 => 1, + 75 => 1, + 76 => 1, + ]; + } + + public function getWarningList() + { + return []; + } +} From 377f541dcb3f6eecf646d3b6f08f16f2adf3dd6a Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 9 Dec 2016 12:51:05 +0000 Subject: [PATCH 028/225] Added WhiteSpace\BlankLine sniff + tests and cs-fixes Sniff allows only one blank line between parts of the code. --- .../Sniffs/WhiteSpace/BlankLineSniff.php | 39 +++++++++++++++++++ ZendCodingStandard/Tests/TestCase.php | 1 - .../Tests/WhiteSpace/BlankLineUnitTest.inc | 30 ++++++++++++++ .../WhiteSpace/BlankLineUnitTest.inc.fixed | 24 ++++++++++++ .../Tests/WhiteSpace/BlankLineUnitTest.php | 24 ++++++++++++ 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php create mode 100644 ZendCodingStandard/Tests/WhiteSpace/BlankLineUnitTest.inc create mode 100644 ZendCodingStandard/Tests/WhiteSpace/BlankLineUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/WhiteSpace/BlankLineUnitTest.php diff --git a/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php b/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php new file mode 100644 index 00000000..a7dc166c --- /dev/null +++ b/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php @@ -0,0 +1,39 @@ +getTokens(); + + $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); + if ($next && $tokens[$stackPtr]['line'] < $tokens[$next]['line'] - 2) { + $fix = $phpcsFile->addFixableError('Unexpected blank line found.', $stackPtr + 1); + + if ($fix) { + $phpcsFile->fixer->replaceToken($stackPtr + 1, ''); + } + } + } +} diff --git a/ZendCodingStandard/Tests/TestCase.php b/ZendCodingStandard/Tests/TestCase.php index 583076be..b8e5658c 100644 --- a/ZendCodingStandard/Tests/TestCase.php +++ b/ZendCodingStandard/Tests/TestCase.php @@ -83,7 +83,6 @@ final public function testSniff() )); } - $failures = $this->generateFailureMessages($phpcsFile); $failureMessages = array_merge($failureMessages, $failures); diff --git a/ZendCodingStandard/Tests/WhiteSpace/BlankLineUnitTest.inc b/ZendCodingStandard/Tests/WhiteSpace/BlankLineUnitTest.inc new file mode 100644 index 00000000..a0097035 --- /dev/null +++ b/ZendCodingStandard/Tests/WhiteSpace/BlankLineUnitTest.inc @@ -0,0 +1,30 @@ + 1, + 6 => 1, + 10 => 1, + 11 => 1, + 18 => 1, + 26 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From aeb3011284742f1d44db8026c8e0b49f037bf1a6 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 15 Dec 2016 13:29:03 +0000 Subject: [PATCH 029/225] Added new sniffs with tests - ZendCodingStandard.Formatting.DoubleColon (no spaces before and after) - ZendCodingStandard.Formatting.NewKeyword (one space after) - ZendCodingStandard.Formatting.NoSpaceAfterSplat (no space after ...) --- .../Sniffs/Formatting/DoubleColonSniff.php | 44 +++++++++++++++++++ .../Sniffs/Formatting/NewKeywordSniff.php | 42 ++++++++++++++++++ .../Formatting/NoSpaceAfterSplatSniff.php | 35 +++++++++++++++ .../Tests/Formatting/DoubleColonUnitTest.inc | 33 ++++++++++++++ .../Formatting/DoubleColonUnitTest.inc.fixed | 27 ++++++++++++ .../Tests/Formatting/DoubleColonUnitTest.php | 25 +++++++++++ .../Tests/Formatting/NewKeywordUnitTest.inc | 18 ++++++++ .../Formatting/NewKeywordUnitTest.inc.fixed | 17 +++++++ .../Tests/Formatting/NewKeywordUnitTest.php | 25 +++++++++++ .../Formatting/NoSpaceAfterSplatUnitTest.inc | 18 ++++++++ .../NoSpaceAfterSplatUnitTest.inc.fixed | 18 ++++++++ .../Formatting/NoSpaceAfterSplatUnitTest.php | 23 ++++++++++ 12 files changed, 325 insertions(+) create mode 100644 ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php create mode 100644 ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php create mode 100644 ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php create mode 100644 ZendCodingStandard/Tests/Formatting/DoubleColonUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Formatting/DoubleColonUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Formatting/DoubleColonUnitTest.php create mode 100644 ZendCodingStandard/Tests/Formatting/NewKeywordUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Formatting/NewKeywordUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Formatting/NewKeywordUnitTest.php create mode 100644 ZendCodingStandard/Tests/Formatting/NoSpaceAfterSplatUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Formatting/NoSpaceAfterSplatUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Formatting/NoSpaceAfterSplatUnitTest.php diff --git a/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php b/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php new file mode 100644 index 00000000..f2ed5728 --- /dev/null +++ b/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php @@ -0,0 +1,44 @@ +getTokens(); + + if ($tokens[$stackPtr - 1]['code'] === T_WHITESPACE) { + $error = 'A double colon must not be preceded by a whitespace.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr); + + if ($fix) { + $phpcsFile->fixer->replaceToken($stackPtr - 1, ''); + } + } + + if ($tokens[$stackPtr + 1]['code'] === T_WHITESPACE) { + $error = 'A double colon must not be followed by a whitespace.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr); + + if ($fix) { + $phpcsFile->fixer->replaceToken($stackPtr + 1, ''); + } + } + } +} diff --git a/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php b/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php new file mode 100644 index 00000000..e23642a2 --- /dev/null +++ b/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php @@ -0,0 +1,42 @@ +getTokens(); + + if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) { + $error = 'A "new" keyword must be followed by a single space.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr); + + if ($fix) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } elseif ($tokens[$stackPtr + 1]['content'] !== ' ') { + $error = 'A "new" keyword must be followed by a single space.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr); + + if ($fix) { + $phpcsFile->fixer->replaceToken($stackPtr + 1, ' '); + } + } + } +} diff --git a/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php b/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php new file mode 100644 index 00000000..f71219c0 --- /dev/null +++ b/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php @@ -0,0 +1,35 @@ +getTokens(); + + if ($tokens[$stackPtr + 1]['code'] === T_WHITESPACE) { + $error = 'A splat operator must not be followed by a space'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceFound'); + + if ($fix) { + $phpcsFile->fixer->replaceToken($stackPtr + 1, ''); + } + } + } +} diff --git a/ZendCodingStandard/Tests/Formatting/DoubleColonUnitTest.inc b/ZendCodingStandard/Tests/Formatting/DoubleColonUnitTest.inc new file mode 100644 index 00000000..7aa29d57 --- /dev/null +++ b/ZendCodingStandard/Tests/Formatting/DoubleColonUnitTest.inc @@ -0,0 +1,33 @@ + 2, + 7 => 2, + 10 => 2, + // 14 => 2, // double colon is preceded by and followed by comments + 18 => 2, + 24 => 2, + 31 => 2, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} diff --git a/ZendCodingStandard/Tests/Formatting/NewKeywordUnitTest.inc b/ZendCodingStandard/Tests/Formatting/NewKeywordUnitTest.inc new file mode 100644 index 00000000..df26b507 --- /dev/null +++ b/ZendCodingStandard/Tests/Formatting/NewKeywordUnitTest.inc @@ -0,0 +1,18 @@ + 1, // not checking next character after space + 6 => 1, + 8 => 1, + 10 => 1, + 14 => 1, + 16 => 1, + 18 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} diff --git a/ZendCodingStandard/Tests/Formatting/NoSpaceAfterSplatUnitTest.inc b/ZendCodingStandard/Tests/Formatting/NoSpaceAfterSplatUnitTest.inc new file mode 100644 index 00000000..b0f8cd14 --- /dev/null +++ b/ZendCodingStandard/Tests/Formatting/NoSpaceAfterSplatUnitTest.inc @@ -0,0 +1,18 @@ + 1, + 5 => 1, + 11 => 1, + 13 => 1, + // 18 => 1, // we are not checking what it the next character after splat op + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 9019d1ad84a84d4a2faf2f7947385def5444fe3f Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 15 Dec 2016 22:06:37 +0000 Subject: [PATCH 030/225] Added ZendCodingStandard.PHP.InstantiatingParenthesis sniff + tests --- .../PHP/InstantiatingParenthesisSniff.php | 48 +++++++++++++++++++ .../PHP/InstantiatingParenthesisUnitTest.inc | 30 ++++++++++++ ...InstantiatingParenthesisUnitTest.inc.fixed | 30 ++++++++++++ .../PHP/InstantiatingParenthesisUnitTest.php | 29 +++++++++++ 4 files changed, 137 insertions(+) create mode 100644 ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php create mode 100644 ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc create mode 100644 ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.php diff --git a/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php b/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php new file mode 100644 index 00000000..f66d818b --- /dev/null +++ b/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php @@ -0,0 +1,48 @@ +getTokens(); + + $end = $phpcsFile->findNext( + array_merge(PHP_CodeSniffer_Tokens::$emptyTokens, [ + T_NS_SEPARATOR, + T_STRING, + T_VARIABLE, + T_STATIC, + ]), + $stackPtr + 1, + null, + true + ); + + if ($tokens[$end]['code'] !== T_OPEN_PARENTHESIS) { + $error = 'Missing parenthesis on instantiating a new class.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr); + + if ($fix) { + $phpcsFile->fixer->addContentBefore($end, '()'); + } + } + } +} diff --git a/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc b/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc new file mode 100644 index 00000000..6bef57a7 --- /dev/null +++ b/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc @@ -0,0 +1,30 @@ +format('Y-m-d') +); + +class MyClass { + public function __construct(DateTime $dt = null, $param = '') {} + + static public function instance() { + return new self; + } + + static public function staticInstance() { + return new static; + } +} + +new MyClass; +new MyClass(new DateTime); +new MyClass(new DateTime, $_GET); + +$var = DateTime::class; +new $var; + +[new DateTime]; +array(new DateTime); diff --git a/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc.fixed b/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc.fixed new file mode 100644 index 00000000..33351b16 --- /dev/null +++ b/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc.fixed @@ -0,0 +1,30 @@ +format('Y-m-d') +); + +class MyClass { + public function __construct(DateTime $dt = null, $param = '') {} + + static public function instance() { + return new self(); + } + + static public function staticInstance() { + return new static(); + } +} + +new MyClass(); +new MyClass(new DateTime()); +new MyClass(new DateTime(), $_GET); + +$var = DateTime::class; +new $var(); + +[new DateTime()]; +array(new DateTime()); diff --git a/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.php b/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.php new file mode 100644 index 00000000..a4be9a69 --- /dev/null +++ b/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.php @@ -0,0 +1,29 @@ + 1, + 4 => 1, + 7 => 1, + 14 => 1, + 18 => 1, + 22 => 1, + 23 => 1, + 24 => 1, + 27 => 1, + 29 => 1, + 30 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 154bf21b48440163beb1ff3db26a69f266d588b4 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 15 Dec 2016 23:06:23 +0000 Subject: [PATCH 031/225] PHP\InstantiatingParenthesis fix for anonymous classes and furureproof approach for "new self" - see issue https://github.com/squizlabs/PHP_CodeSniffer/issues/1245 --- .../Sniffs/PHP/InstantiatingParenthesisSniff.php | 13 +++++++++++-- .../Tests/PHP/InstantiatingParenthesisUnitTest.inc | 3 +++ .../PHP/InstantiatingParenthesisUnitTest.inc.fixed | 3 +++ .../Tests/PHP/InstantiatingParenthesisUnitTest.php | 2 ++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php b/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php index f66d818b..e127bff3 100644 --- a/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php +++ b/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php @@ -26,10 +26,12 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $end = $phpcsFile->findNext( array_merge(PHP_CodeSniffer_Tokens::$emptyTokens, [ + T_ANON_CLASS, T_NS_SEPARATOR, + T_SELF, // currently not used, @see https://github.com/squizlabs/PHP_CodeSniffer/issues/1245 + T_STATIC, T_STRING, T_VARIABLE, - T_STATIC, ]), $stackPtr + 1, null, @@ -37,11 +39,18 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) ); if ($tokens[$end]['code'] !== T_OPEN_PARENTHESIS) { + $last = $phpcsFile->findPrevious( + PHP_CodeSniffer_Tokens::$emptyTokens, + $end - 1, + $stackPtr + 1, + true + ); + $error = 'Missing parenthesis on instantiating a new class.'; $fix = $phpcsFile->addFixableError($error, $stackPtr); if ($fix) { - $phpcsFile->fixer->addContentBefore($end, '()'); + $phpcsFile->fixer->addContent($last, '()'); } } } diff --git a/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc b/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc index 6bef57a7..5c27e8f4 100644 --- a/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc +++ b/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc @@ -28,3 +28,6 @@ new $var; [new DateTime]; array(new DateTime); + +$anonymousClass = new class{}; +$anonymousClass = new class {}; diff --git a/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc.fixed b/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc.fixed index 33351b16..8437beb7 100644 --- a/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc.fixed +++ b/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.inc.fixed @@ -28,3 +28,6 @@ new $var(); [new DateTime()]; array(new DateTime()); + +$anonymousClass = new class(){}; +$anonymousClass = new class() {}; diff --git a/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.php b/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.php index a4be9a69..64889eb4 100644 --- a/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.php +++ b/ZendCodingStandard/Tests/PHP/InstantiatingParenthesisUnitTest.php @@ -19,6 +19,8 @@ public function getErrorList($testFile = '') 27 => 1, 29 => 1, 30 => 1, + 32 => 1, + 33 => 1, ]; } From 76d30f571984d968139dd04a28d6c6cd33a7eab0 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 15 Dec 2016 23:07:08 +0000 Subject: [PATCH 032/225] Added PHP\RedundantSemicolon sniff + tests --- .../Sniffs/PHP/RedundantSemicolonSniff.php | 55 +++++++++++++++++++ .../Tests/PHP/RedundantSemicolonUnitTest.inc | 24 ++++++++ .../PHP/RedundantSemicolonUnitTest.inc.fixed | 24 ++++++++ .../Tests/PHP/RedundantSemicolonUnitTest.php | 22 ++++++++ 4 files changed, 125 insertions(+) create mode 100644 ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php create mode 100644 ZendCodingStandard/Tests/PHP/RedundantSemicolonUnitTest.inc create mode 100644 ZendCodingStandard/Tests/PHP/RedundantSemicolonUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/PHP/RedundantSemicolonUnitTest.php diff --git a/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php b/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php new file mode 100644 index 00000000..ec8713a6 --- /dev/null +++ b/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php @@ -0,0 +1,55 @@ +getTokens(); + + if (! isset($tokens[$stackPtr]['scope_condition'])) { + return; + } + + $scopeCondition = $tokens[$stackPtr]['scope_condition']; + if (in_array($tokens[$scopeCondition]['code'], [T_ANON_CLASS, T_CLOSURE])) { + return; + } + + $nextNonEmpty = $phpcsFile->findNext( + PHP_CodeSniffer_Tokens::$emptyTokens, + $stackPtr + 1, + null, + true + ); + + if ($tokens[$nextNonEmpty]['code'] === T_SEMICOLON) { + $error = 'Redundant semicolon after control structure "%s".'; + $data = [ + strtolower($tokens[$scopeCondition]['content']), + ]; + $fix = $phpcsFile->addFixableError($error, $nextNonEmpty, '', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($nextNonEmpty, ''); + } + } + } +} diff --git a/ZendCodingStandard/Tests/PHP/RedundantSemicolonUnitTest.inc b/ZendCodingStandard/Tests/PHP/RedundantSemicolonUnitTest.inc new file mode 100644 index 00000000..a149ae40 --- /dev/null +++ b/ZendCodingStandard/Tests/PHP/RedundantSemicolonUnitTest.inc @@ -0,0 +1,24 @@ + 0) { +}; + +while (0) { +}; + +for (;;) { +}; + +switch (true) { +}; + +$closure = function() { +}; + +$class = new class { +}; + +$class = new class() extends \DateTime implements \ArrayAccess { +}; + +$a = $b{0}; diff --git a/ZendCodingStandard/Tests/PHP/RedundantSemicolonUnitTest.inc.fixed b/ZendCodingStandard/Tests/PHP/RedundantSemicolonUnitTest.inc.fixed new file mode 100644 index 00000000..0ded4c9e --- /dev/null +++ b/ZendCodingStandard/Tests/PHP/RedundantSemicolonUnitTest.inc.fixed @@ -0,0 +1,24 @@ + 0) { +} + +while (0) { +} + +for (;;) { +} + +switch (true) { +} + +$closure = function() { +}; + +$class = new class { +}; + +$class = new class() extends \DateTime implements \ArrayAccess { +}; + +$a = $b{0}; diff --git a/ZendCodingStandard/Tests/PHP/RedundantSemicolonUnitTest.php b/ZendCodingStandard/Tests/PHP/RedundantSemicolonUnitTest.php new file mode 100644 index 00000000..9101956c --- /dev/null +++ b/ZendCodingStandard/Tests/PHP/RedundantSemicolonUnitTest.php @@ -0,0 +1,22 @@ + 1, + 7 => 1, + 10 => 1, + 13 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 53797d3502faa01f6a98065a56f4120e3d3eac63 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 8 Feb 2017 13:00:10 +0000 Subject: [PATCH 033/225] Added new sniff `LogicalOperatorNotAtTheEndOfTheLine` - disallow logical operators to be at the end of the line --- ...gicalOperatorNotAtTheEndOfTheLineSniff.php | 59 +++++++++++++++++++ ...OperatorNotAtTheEndOfTheLineUnitTest.fixed | 25 ++++++++ ...alOperatorNotAtTheEndOfTheLineUnitTest.inc | 25 ++++++++ ...alOperatorNotAtTheEndOfTheLineUnitTest.php | 25 ++++++++ 4 files changed, 134 insertions(+) create mode 100644 ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php create mode 100644 ZendCodingStandard/Tests/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.fixed create mode 100644 ZendCodingStandard/Tests/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.php diff --git a/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php b/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php new file mode 100644 index 00000000..d6abdd81 --- /dev/null +++ b/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php @@ -0,0 +1,59 @@ +getTokens(); + + $prev = $phpcsFile->findPrevious( + PHP_CodeSniffer_Tokens::$emptyTokens, + $stackPtr - 1, + null, + true + ); + $next = $phpcsFile->findNext( + PHP_CodeSniffer_Tokens::$emptyTokens, + $stackPtr + 1, + null, + true + ); + + if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line'] + && $tokens[$next]['line'] !== $tokens[$stackPtr]['line'] + ) { + $fix = $phpcsFile->addFixableError('Logical operator cannot be at the end of the line.', $stackPtr); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($stackPtr, ''); + for ($i = $stackPtr - 1; $i > $prev; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->addContentBefore($next, $tokens[$stackPtr]['content'] . ' '); + $phpcsFile->fixer->endChangeset(); + } + } + } +} diff --git a/ZendCodingStandard/Tests/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.fixed b/ZendCodingStandard/Tests/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.fixed new file mode 100644 index 00000000..6fb136b3 --- /dev/null +++ b/ZendCodingStandard/Tests/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.fixed @@ -0,0 +1,25 @@ + 1, + 6 => 1, + 9 => 1, + 12 => 1, + 15 => 1, + 16 => 1, + 19 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 9549ba1bdfeef8dcec063f05836b2632b019488d Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 9 Feb 2017 22:19:33 +0000 Subject: [PATCH 034/225] Rename .fixed file --- ...ixed => LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc.fixed} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ZendCodingStandard/Tests/Operators/{LogicalOperatorNotAtTheEndOfTheLineUnitTest.fixed => LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc.fixed} (100%) diff --git a/ZendCodingStandard/Tests/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.fixed b/ZendCodingStandard/Tests/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc.fixed similarity index 100% rename from ZendCodingStandard/Tests/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.fixed rename to ZendCodingStandard/Tests/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc.fixed From b488b16e3eabfca3120d9c840b0664502c9da26b Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 9 Feb 2017 22:23:07 +0000 Subject: [PATCH 035/225] Added traits sniffs with tests - Classes\AlphabeticallySortedTraits - Classes\TraitUsage --- ZendCodingStandard/CodingStandard.php | 29 ++- .../AlphabeticallySortedTraitsSniff.php | 152 ++++++++++++ .../Sniffs/Classes/TraitUsageSniff.php | 227 ++++++++++++++++++ .../AlphabeticallySortedTraitsUnitTest.inc | 41 ++++ ...phabeticallySortedTraitsUnitTest.inc.fixed | 40 +++ .../AlphabeticallySortedTraitsUnitTest.php | 20 ++ .../Tests/Classes/TraitUsageUnitTest.inc | 40 +++ .../Classes/TraitUsageUnitTest.inc.fixed | 44 ++++ .../Tests/Classes/TraitUsageUnitTest.php | 27 +++ 9 files changed, 619 insertions(+), 1 deletion(-) create mode 100644 ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php create mode 100644 ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php create mode 100644 ZendCodingStandard/Tests/Classes/AlphabeticallySortedTraitsUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Classes/AlphabeticallySortedTraitsUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Classes/AlphabeticallySortedTraitsUnitTest.php create mode 100644 ZendCodingStandard/Tests/Classes/TraitUsageUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Classes/TraitUsageUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Classes/TraitUsageUnitTest.php diff --git a/ZendCodingStandard/CodingStandard.php b/ZendCodingStandard/CodingStandard.php index fb6a788c..21a5eb23 100644 --- a/ZendCodingStandard/CodingStandard.php +++ b/ZendCodingStandard/CodingStandard.php @@ -1,6 +1,10 @@ getTokens(); + + // Ignore USE keywords inside closures. + $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true); + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + return false; + } + + // Ignore global USE keywords. + if (! $phpcsFile->hasCondition($stackPtr, [T_CLASS, T_TRAIT, T_ANON_CLASS])) { + return false; + } + + return true; } } diff --git a/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php b/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php new file mode 100644 index 00000000..810197f7 --- /dev/null +++ b/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php @@ -0,0 +1,152 @@ +getTraits($phpcsFile, $stackPtr); + + $lastUse = null; + foreach ($uses as $use) { + if (! $lastUse) { + $lastUse = $use; + continue; + } + + $order = $this->compareUseStatements($use, $lastUse); + + if ($order < 0) { + $error = 'Traits are incorrectly ordered. The first wrong one is %s'; + $data = [$use['name']]; + $fix = $phpcsFile->addFixableError($error, $use['ptrUse'], '', $data); + + if ($fix) { + $this->fixAlphabeticalOrder($phpcsFile, $uses); + } + + return; + } + + $lastUse = $use; + } + } + + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $scopePtr + * @return array[] + */ + private function getTraits(PHP_CodeSniffer_File $phpcsFile, $scopePtr) + { + $tokens = $phpcsFile->getTokens(); + + $uses = []; + + $start = $tokens[$scopePtr]['scope_opener']; + $end = $tokens[$scopePtr]['scope_closer']; + while ($use = $phpcsFile->findNext(T_USE, $start + 1, $end)) { + if (! CodingStandard::isTraitUse($phpcsFile, $use) + || ! isset($tokens[$use]['conditions'][$scopePtr]) + || $tokens[$use]['level'] !== $tokens[$scopePtr]['level'] + 1 + ) { + $start = $use; + continue; + } + + // Find comma, semicolon or opening curly bracket, whatever is first. + $endOfName = $phpcsFile->findNext( + [T_COMMA, T_SEMICOLON, T_OPEN_CURLY_BRACKET], + $use + 1 + ); + + // Find end of scope - could be semicolon or closing curly bracket. + $endOfScope = $this->getEndOfTraitScope($phpcsFile, $endOfName); + + $uses[] = [ + 'ptrUse' => $use, + 'name' => trim($phpcsFile->getTokensAsString($use + 1, $endOfName - $use - 1)), + 'ptrEnd' => $endOfScope, + 'string' => trim($phpcsFile->getTokensAsString($use, $endOfScope - $use + 1)), + ]; + + $start = $endOfName; + } + + return $uses; + } + + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @return int + */ + private function getEndOfTraitScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_COMMA) { + $stackPtr = $phpcsFile->findNext([T_SEMICOLON, T_OPEN_CURLY_BRACKET], $stackPtr + 1); + } + + if ($tokens[$stackPtr]['code'] === T_SEMICOLON) { + return $stackPtr; + } + + return $phpcsFile->findNext(T_CLOSE_CURLY_BRACKET, $stackPtr + 1); + } + + /** + * @param array $a + * @param array $b + * @return int + */ + private function compareUseStatements(array $a, array $b) + { + return strnatcasecmp($a['name'], $b['name']); + } + + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param array[] $uses + * @return void + */ + private function fixAlphabeticalOrder(PHP_CodeSniffer_File $phpcsFile, array $uses) + { + $first = reset($uses); + $last = end($uses); + $lastScopeCloser = $last['ptrEnd']; + + $phpcsFile->fixer->beginChangeset(); + for ($i = $first['ptrUse']; $i <= $lastScopeCloser; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + uasort($uses, function (array $a, array $b) { + return $this->compareUseStatements($a, $b); + }); + + $phpcsFile->fixer->addContent($first['ptrUse'], implode($phpcsFile->eolChar, array_map(function ($use) { + return $use['string']; + }, $uses))); + + $phpcsFile->fixer->endChangeset(); + } +} diff --git a/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php b/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php new file mode 100644 index 00000000..0f3aaa37 --- /dev/null +++ b/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php @@ -0,0 +1,227 @@ +getTokens(); + + // No blank line before use keyword. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); + if ($tokens[$prev]['line'] + 1 !== $tokens[$stackPtr]['line']) { + $error = 'Blank line is not allowed before trait declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $prev + 1; $i < $stackPtr; ++$i) { + if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->endChangeset(); + } + } + + // One space after the use keyword. + if ($tokens[$stackPtr + 1]['content'] !== ' ') { + $error = 'There must be a single space after USE keyword'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterUse'); + + if ($fix) { + if ($tokens[$stackPtr + 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($stackPtr + 1, ' '); + } else { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } + } + + $scopeOpener = $phpcsFile->findNext([T_OPEN_CURLY_BRACKET, T_SEMICOLON], $stackPtr + 1); + + $comma = $phpcsFile->findNext(T_COMMA, $stackPtr + 1, $scopeOpener - 1); + if ($comma) { + $error = 'There must be one USE per declaration.'; + $fix = $phpcsFile->addFixableError($error, $comma); + + if ($fix) { + $phpcsFile->fixer->replaceToken($comma, ';' . $phpcsFile->eolChar . 'use '); + } + } + + // Check for T_WHITESPACE in trait name. + $firstNotEmpty = $phpcsFile->findNext( + T_WHITESPACE, + $stackPtr + 1, + $comma ?: $scopeOpener, + true + ); + $lastNotEmpty = $phpcsFile->findPrevious( + T_WHITESPACE, + ($comma ?: $scopeOpener) - 1, + $stackPtr + 1, + true + ); + + if ($firstNotEmpty !== $lastNotEmpty) { + $emptyInName = $phpcsFile->findNext( + PHP_CodeSniffer_Tokens::$emptyTokens, + $firstNotEmpty + 1, + $lastNotEmpty + ); + if ($emptyInName) { + $error = 'Empty token %s is not allowed in trait name.'; + $data = [$tokens[$emptyInName]['type']]; + $fix = $phpcsFile->addFixableError($error, $emptyInName, '', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($emptyInName, ''); + } + } + } + + if ($tokens[$scopeOpener]['code'] === T_OPEN_CURLY_BRACKET) { + $prevNonEmpty = $phpcsFile->findPrevious( + PHP_CodeSniffer_Tokens::$emptyTokens, + $scopeOpener - 1, + null, + true + ); + if ($tokens[$prevNonEmpty]['line'] !== $tokens[$scopeOpener]['line']) { + $error = 'There must be a single space before curly bracket.'; + $fix = $phpcsFile->addFixableError($error, $scopeOpener, 'SpaceBeforeCurly'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $prevNonEmpty + 1; $i < $scopeOpener; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->addContentBefore($scopeOpener, ' '); + $phpcsFile->fixer->endChangeset(); + } + } elseif ($tokens[$scopeOpener - 1]['content'] !== ' ') { + $error = 'There must be a single space before curly bracket.'; + $fix = $phpcsFile->addFixableError($error, $scopeOpener, 'SpaceBeforeCurly'); + + if ($fix) { + if ($tokens[$scopeOpener - 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($scopeOpener - 1, ' '); + } else { + $phpcsFile->fixer->addContent($scopeOpener - 1, ' '); + } + } + } + + $nextNonEmpty = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $scopeOpener + 1, null, true); + if ($tokens[$nextNonEmpty]['line'] !== $tokens[$scopeOpener]['line'] + 1) { + $error = 'Content must be in next line after opening curly bracket.'; + $fix = $phpcsFile->addFixableError($error, $scopeOpener); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $scopeOpener + 1; $i < $nextNonEmpty; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->addContentBefore($nextNonEmpty, $phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } + + $scopeCloser = $tokens[$scopeOpener]['scope_closer']; + $prevNonEmpty = $phpcsFile->findPrevious( + PHP_CodeSniffer_Tokens::$emptyTokens, + $scopeCloser - 1, + null, + true + ); + if ($tokens[$prevNonEmpty]['line'] + 1 !== $tokens[$scopeCloser]['line']) { + $error = 'Close curly bracket must be in next line after content.'; + $fix = $phpcsFile->addFixableError($error, $scopeCloser); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $prevNonEmpty + 1; $i < $scopeCloser; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->addContentBefore($scopeCloser, $phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } + } else { + $scopeCloser = $scopeOpener; + } + + $class = $phpcsFile->findPrevious([T_CLASS, T_TRAIT, T_ANON_CLASS], $stackPtr - 1); + // Only interested in the last USE statement from here onwards. + $nextUse = $stackPtr; + do { + $nextUse = $phpcsFile->findNext(T_USE, $nextUse + 1, $tokens[$class]['scope_closer']); + } while ($nextUse !== false + && (! CodingStandard::isTraitUse($phpcsFile, $nextUse) + || ! isset($tokens[$nextUse]['conditions'][$class]) + || $tokens[$nextUse]['level'] !== $tokens[$class]['level'] + 1 + ) + ); + + if ($nextUse !== false) { + return; + } + + // todo: check order of statements in curly brackets + + // Find next (after traits) non-whitespace token. + $next = $phpcsFile->findNext(T_WHITESPACE, $scopeCloser + 1, null, true); + + $diff = $tokens[$next]['line'] - $tokens[$scopeCloser]['line'] - 1; + if ($diff !== 1 + && $tokens[$next]['code'] !== T_CLOSE_CURLY_BRACKET + ) { + $error = 'There must be one blank line after the last USE statement; %s found;'; + $data = [$diff]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterLastUse', $data); + + if ($fix) { + if ($diff === 0) { + $phpcsFile->fixer->addNewline($scopeCloser); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = $scopeCloser + 1; $i < $next; ++$i) { + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->addNewline($scopeCloser); + $phpcsFile->fixer->endChangeset(); + } + } + } + } +} diff --git a/ZendCodingStandard/Tests/Classes/AlphabeticallySortedTraitsUnitTest.inc b/ZendCodingStandard/Tests/Classes/AlphabeticallySortedTraitsUnitTest.inc new file mode 100644 index 00000000..6ac1d5e3 --- /dev/null +++ b/ZendCodingStandard/Tests/Classes/AlphabeticallySortedTraitsUnitTest.inc @@ -0,0 +1,41 @@ + 1, + 36 => 1, + ]; + } + + public function getWarningList() + { + return []; + } +} diff --git a/ZendCodingStandard/Tests/Classes/TraitUsageUnitTest.inc b/ZendCodingStandard/Tests/Classes/TraitUsageUnitTest.inc new file mode 100644 index 00000000..b04e049a --- /dev/null +++ b/ZendCodingStandard/Tests/Classes/TraitUsageUnitTest.inc @@ -0,0 +1,40 @@ + 1, + 11 => 1, + 12 => 1, + 15 => 2, + 17 => 1, + 20 => 2, + 25 => 3, + 26 => 4, + 35 => 1, + ]; + } + + public function getWarningList() + { + return []; + } +} From 0eebc820de94ff818cb30d0d5a2ae193f7e375d5 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 9 Feb 2017 22:25:50 +0000 Subject: [PATCH 036/225] Added isGlobalUse method --- ZendCodingStandard/CodingStandard.php | 23 +++++++++++++++++++ .../Classes/UnusedUseStatementSniff.php | 3 ++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/ZendCodingStandard/CodingStandard.php b/ZendCodingStandard/CodingStandard.php index 21a5eb23..b3d17080 100644 --- a/ZendCodingStandard/CodingStandard.php +++ b/ZendCodingStandard/CodingStandard.php @@ -88,4 +88,27 @@ public static function isTraitUse(PHP_CodeSniffer_File $phpcsFile, $stackPtr) return true; } + + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @return bool + */ + public static function isGlobalUse(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore USE keywords inside closures. + $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true); + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + return false; + } + + // Ignore USE keywords for traits. + if ($phpcsFile->hasCondition($stackPtr, [T_CLASS, T_TRAIT, T_ANON_CLASS])) { + return false; + } + + return true; + } } diff --git a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php index 1237e8d6..a987d96a 100644 --- a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php +++ b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php @@ -13,6 +13,7 @@ use PHP_CodeSniffer_File; use PHP_CodeSniffer_Sniff; use PHP_CodeSniffer_Tokens; +use ZendCodingStandard\CodingStandard; /** * Checks for "use" statements that are not needed in a file. @@ -47,7 +48,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $tokens = $phpcsFile->getTokens(); // Only check use statements in the global scope. - if (! empty($tokens[$stackPtr]['conditions'])) { + if (! CodingStandard::isGlobalUse($phpcsFile, $stackPtr)) { return; } From 572fadcae955fb999d0e21cd3ab95ebdbc91f229 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 9 Feb 2017 22:26:55 +0000 Subject: [PATCH 037/225] Updated comments and PHPDocs --- ZendCodingStandard/Sniffs/Arrays/FormatSniff.php | 4 ++-- .../Sniffs/Arrays/TrailingArrayCommaSniff.php | 10 +++++----- .../Sniffs/Classes/UnusedUseStatementSniff.php | 12 ++++-------- .../Sniffs/Commenting/DocCommentSniff.php | 2 +- ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php | 6 ++++++ .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 2 +- .../Sniffs/PHP/InstantiatingParenthesisSniff.php | 2 +- .../Sniffs/PHP/RedundantSemicolonSniff.php | 2 +- .../Sniffs/WhiteSpace/BlankLineSniff.php | 2 +- .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 8 +++++--- .../Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php | 2 +- 11 files changed, 28 insertions(+), 24 deletions(-) diff --git a/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index a50530a2..7c24c603 100644 --- a/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -14,7 +14,7 @@ class FormatSniff implements PHP_CodeSniffer_Sniff public $indent = 4; /** - * @return array + * @return int[] */ public function register() { @@ -119,7 +119,7 @@ private function multiLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $expected = $indent + $this->indent; - // Checks array element indent. + // Check array element indent. if ($firstOnLine = $phpcsFile->findFirstOnLine(T_WHITESPACE, $next)) { $found = strlen($tokens[$firstOnLine]['content']); if ($found !== $expected) { diff --git a/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php b/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php index a7f6388a..a68987da 100644 --- a/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php +++ b/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php @@ -10,17 +10,17 @@ class TrailingArrayCommaSniff implements PHP_CodeSniffer_Sniff { + /** + * @return int[] + */ public function register() { return [T_OPEN_SHORT_ARRAY]; } /** - * Processes this test, when one of its tokens is encountered. - * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token in - * the stack passed in $tokens. + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) diff --git a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php index a987d96a..36d32281 100644 --- a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php +++ b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php @@ -26,9 +26,7 @@ class UnusedUseStatementSniff implements PHP_CodeSniffer_Sniff { /** - * Returns an array of tokens this test wants to listen for. - * - * @return array + * @return int[] */ public function register() { @@ -36,11 +34,8 @@ public function register() } /** - * Processes this test, when one of its tokens is encountered. - * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token in - * the stack passed in $tokens. + * @param PHP_CodeSniffer_File $phpcsFile The + * @param int $stackPtr * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) @@ -53,6 +48,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } // Seek to the end of the statement and get the string before the semi colon. + // It works only with one USE keyword per declaration. $semiColon = $phpcsFile->findEndOfStatement($stackPtr); if ($tokens[$semiColon]['code'] !== T_SEMICOLON) { return; diff --git a/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index a1b83d4d..1dbd249f 100644 --- a/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -7,7 +7,7 @@ class DocCommentSniff implements PHP_CodeSniffer_Sniff { /** - * @return array + * @return int[] */ public function register() { diff --git a/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php b/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php index c96195a6..be5ae099 100644 --- a/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php +++ b/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php @@ -14,6 +14,12 @@ public function __construct() parent::__construct([T_CLASS, T_INTERFACE, T_TRAIT], [T_FUNCTION]); } + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @param int $currScope + * @return void + */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $tokens = $phpcsFile->getTokens(); diff --git a/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index 3433c3b1..3e180f1e 100644 --- a/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -27,7 +27,7 @@ public function __construct() } /** - * @return array + * @return int[] */ public function register() { diff --git a/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php b/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php index e127bff3..e9fd23d4 100644 --- a/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php +++ b/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php @@ -28,7 +28,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) array_merge(PHP_CodeSniffer_Tokens::$emptyTokens, [ T_ANON_CLASS, T_NS_SEPARATOR, - T_SELF, // currently not used, @see https://github.com/squizlabs/PHP_CodeSniffer/issues/1245 + T_SELF, T_STATIC, T_STRING, T_VARIABLE, diff --git a/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php b/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php index ec8713a6..47bccf69 100644 --- a/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php +++ b/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php @@ -8,7 +8,7 @@ class RedundantSemicolonSniff implements PHP_CodeSniffer_Sniff { /** - * @return array + * @return int[] */ public function register() { diff --git a/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php b/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php index a7dc166c..38cb8e61 100644 --- a/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php +++ b/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php @@ -7,7 +7,7 @@ class BlankLineSniff implements PHP_CodeSniffer_Sniff { /** - * @return array + * @return int[] */ public function register() { diff --git a/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index 9444e7f4..40c60da3 100644 --- a/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -20,15 +20,17 @@ class CommaSpacingSniff implements PHP_CodeSniffer_Sniff { + /** + * @return int[] + */ public function register() { return [T_COMMA]; } /** - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) diff --git a/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php b/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php index 9446cf0a..e052baa8 100644 --- a/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php +++ b/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php @@ -7,7 +7,7 @@ class NoBlankLineAtStartSniff implements PHP_CodeSniffer_Sniff { /** - * @return array + * @return int[] */ public function register() { From c5b45ad6eefe3af6099099a5bd10338bd5fafe59 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 9 Feb 2017 22:27:54 +0000 Subject: [PATCH 038/225] Updated conditions --- .../Sniffs/Classes/UnusedUseStatementSniff.php | 7 ++++--- ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php | 6 +++--- .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 2 +- ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php | 2 +- ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php index 36d32281..4401cc63 100644 --- a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php +++ b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php @@ -156,10 +156,11 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) ) { return; } - } elseif ($tokens[$beforeUsage]['code'] === T_DOC_COMMENT_TAG && - in_array( + } elseif ($tokens[$beforeUsage]['code'] === T_DOC_COMMENT_TAG + && in_array( $tokens[$beforeUsage]['content'], - ['@var', '@param', '@return', '@throws', '@method'] + ['@var', '@param', '@return', '@throws', '@method'], + true ) ) { return; diff --git a/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index 1dbd249f..b31aae85 100644 --- a/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -484,8 +484,8 @@ private function checkCommentIndents(PHP_CodeSniffer_File $phpcsFile, $commentSt $indent = 0; } } elseif (! $next - || $tokens[$next]['line'] > $tokens[$commentEnd]['line'] + 1 - && in_array($tokens[$next]['code'], $allowEmptyLineBefore) + || ($tokens[$next]['line'] > $tokens[$commentEnd]['line'] + 1 + && in_array($tokens[$next]['code'], $allowEmptyLineBefore, true)) ) { $indent = 0; } else { @@ -554,7 +554,7 @@ private function checkCommentIndents(PHP_CodeSniffer_File $phpcsFile, $commentSt if ($fix) { $phpcsFile->fixer->replaceToken($next - 1, $phpcsFile->eolChar . ' '); } - } elseif ($spaces['code'] == T_DOC_COMMENT_WHITESPACE + } elseif ($spaces['code'] === T_DOC_COMMENT_WHITESPACE && strlen($spaces['content']) !== $indent + 1 ) { $error = 'Invalid doc comment indent. Expected %d spaces; %d found'; diff --git a/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index 3e180f1e..e684dc5e 100644 --- a/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -209,7 +209,7 @@ private function checkExtendsAndImplements(PHP_CodeSniffer_File $phpcsFile, $sta private function checkClass(PHP_CodeSniffer_File $phpcsFile, $start, $end, $isGlobalUse = false) { $class = trim($phpcsFile->getTokensAsString($start, $end - $start)); - if ($class[0] == '\\') { + if ($class[0] === '\\') { $result = $this->hasDifferentCase(ltrim($class, '\\')); if ($result) { $this->error($phpcsFile, $start, $end, '\\' . $result, $class); diff --git a/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php b/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php index 47bccf69..c5fb9548 100644 --- a/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php +++ b/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php @@ -29,7 +29,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } $scopeCondition = $tokens[$stackPtr]['scope_condition']; - if (in_array($tokens[$scopeCondition]['code'], [T_ANON_CLASS, T_CLOSURE])) { + if (in_array($tokens[$scopeCondition]['code'], [T_ANON_CLASS, T_CLOSURE], true)) { return; } diff --git a/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index 40c60da3..29964902 100644 --- a/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -56,7 +56,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) if ($fix) { $phpcsFile->fixer->addContent($stackPtr, ' '); } - } elseif ($nextToken['content'] != ' ') { + } elseif ($nextToken['content'] !== ' ') { // There is more than one space after comma. $nonSpace = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); From e20d51d9ab98ecd4ba0706fd21d92b0aa0265405 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 9 Feb 2017 22:28:10 +0000 Subject: [PATCH 039/225] Removed redundant statement --- ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php index 4401cc63..ed5753ca 100644 --- a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php +++ b/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php @@ -61,10 +61,6 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) true ); - if ($tokens[$classPtr]['code'] !== T_STRING) { - return; - } - // Search where the class name is used. PHP treats class names case // insensitive, that's why we cannot search for the exact class name string // and need to iterate over all T_STRING tokens in the file. From 7aecb2b7349f0ca1005d44883b1ae107142a5088 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 9 Feb 2017 22:28:57 +0000 Subject: [PATCH 040/225] Added more test cases for PHP\LowerCaseKeyword sniff --- .../Tests/PHP/LowerCaseKeywordUnitTest.inc | 2 + .../PHP/LowerCaseKeywordUnitTest.inc.fixed | 2 + .../Tests/PHP/LowerCaseKeywordUnitTest.php | 46 ++++++++++--------- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.inc b/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.inc index ba2019da..1e136302 100644 --- a/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.inc +++ b/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.inc @@ -14,6 +14,8 @@ ABSTRACT CLASS MyClass { PARENT::method(); NEW \DateTime(); + NEW SELF(); + NEW STATIC(); STATIC::method(); SELF::method(); diff --git a/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed b/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed index e4787db2..cf604c8b 100644 --- a/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed +++ b/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed @@ -14,6 +14,8 @@ abstract class MyClass { parent::method(); new \DateTime(); + new self(); + new static(); static::method(); self::method(); diff --git a/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.php b/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.php index 55d62fc8..a6a22727 100644 --- a/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.php +++ b/ZendCodingStandard/Tests/PHP/LowerCaseKeywordUnitTest.php @@ -17,35 +17,37 @@ public function getErrorList($testFile = '') 13 => 3, 15 => 1, 16 => 1, - 18 => 1, - 19 => 1, - 21 => 3, - 22 => 4, - 23 => 1, - 27 => 3, + 17 => 2, + 18 => 2, + 20 => 1, + 21 => 1, + 23 => 3, + 24 => 4, + 25 => 1, 29 => 3, - 31 => 1, - 34 => 1, - 35 => 1, + 31 => 3, + 33 => 1, + 36 => 1, 37 => 1, - 38 => 1, - 41 => 1, - 42 => 1, + 39 => 1, + 40 => 1, 43 => 1, 44 => 1, 45 => 1, 46 => 1, - 47 => 2, - 50 => 1, - 51 => 2, - 53 => 1, - 54 => 1, - 57 => 3, - 59 => 1, - 60 => 1, - 61 => 2, + 47 => 1, + 48 => 1, + 49 => 2, + 52 => 1, + 53 => 2, + 55 => 1, + 56 => 1, + 59 => 3, + 61 => 1, 62 => 1, - 63 => 1, + 63 => 2, + 64 => 1, + 65 => 1, ]; } From 29c5ef62166fcba0c96f05e5710d46b249bb6772 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 9 Feb 2017 22:30:25 +0000 Subject: [PATCH 041/225] Added namespaces sniffs + tests - Namespaces\AlphabeticallySortedUses - Namespaces\ConstAndFunctionKeyword - UseDoesNotStatWithBackslash --- .../AlphabeticallySortedUsesSniff.php | 157 ++++++++++++++++++ .../ConstAndFunctionKeywordsSniff.php | 69 ++++++++ .../UseDoesNotStartWithBackslashSniff.php | 64 +++++++ .../AlphabeticallySortedUsesUnitTest.inc | 27 +++ ...AlphabeticallySortedUsesUnitTest.inc.fixed | 27 +++ .../AlphabeticallySortedUsesUnitTest.php | 20 +++ .../ConstAndFunctionKeywordsUnitTest.inc | 7 + ...ConstAndFunctionKeywordsUnitTest.inc.fixed | 7 + .../ConstAndFunctionKeywordsUnitTest.php | 22 +++ .../UseDoesNotStartWithBackslashUnitTest.inc | 17 ++ ...oesNotStartWithBackslashUnitTest.inc.fixed | 17 ++ .../UseDoesNotStartWithBackslashUnitTest.php | 21 +++ ZendCodingStandard/ruleset.xml | 4 - 13 files changed, 455 insertions(+), 4 deletions(-) create mode 100644 ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php create mode 100644 ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php create mode 100644 ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php create mode 100644 ZendCodingStandard/Tests/Namespaces/AlphabeticallySortedUsesUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Namespaces/AlphabeticallySortedUsesUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Namespaces/AlphabeticallySortedUsesUnitTest.php create mode 100644 ZendCodingStandard/Tests/Namespaces/ConstAndFunctionKeywordsUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Namespaces/ConstAndFunctionKeywordsUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Namespaces/ConstAndFunctionKeywordsUnitTest.php create mode 100644 ZendCodingStandard/Tests/Namespaces/UseDoesNotStartWithBackslashUnitTest.inc create mode 100644 ZendCodingStandard/Tests/Namespaces/UseDoesNotStartWithBackslashUnitTest.inc.fixed create mode 100644 ZendCodingStandard/Tests/Namespaces/UseDoesNotStartWithBackslashUnitTest.php mode change 100644 => 100755 ZendCodingStandard/ruleset.xml diff --git a/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php new file mode 100644 index 00000000..9a3068fc --- /dev/null +++ b/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -0,0 +1,157 @@ +getUseStatements($phpcsFile, $stackPtr); + + $lastUse = null; + foreach ($uses as $use) { + if (! $lastUse) { + $lastUse = $use; + continue; + } + + $order = $this->compareUseStatements($use, $lastUse); + + if ($order < 0) { + $error = 'Use statements are incorrectly ordered. The first wrong one is %s'; + $data = [$use['name']]; + + $fix = $phpcsFile->addFixableError($error, $use['ptrUse'], '', $data); + + if ($fix) { + $this->fixAlphabeticalOrder($phpcsFile, $uses); + } + + return; + } + + $lastUse = $use; + } + } + + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param int $scopePtr + * @return array[] + */ + private function getUseStatements(PHP_CodeSniffer_File $phpcsFile, $scopePtr) + { + $tokens = $phpcsFile->getTokens(); + + $uses = []; + + if (isset($tokens[$scopePtr]['scope_opener'])) { + $start = $tokens[$scopePtr]['scope_opener']; + $end = $tokens[$scopePtr]['scope_closer']; + } else { + $start = $scopePtr; + $end = null; + } + while ($use = $phpcsFile->findNext(T_USE, $start + 1, $end)) { + if (! CodingStandard::isGlobalUse($phpcsFile, $use) + || ! isset($tokens[$use]['conditions'][$scopePtr]) + || $tokens[$use]['level'] !== $tokens[$scopePtr]['level'] + 1 + ) { + $start = $use; + continue; + } + + // find semicolon as the end of the global use scope + $endOfScope = $phpcsFile->findNext([T_SEMICOLON], $use + 1); + + $startOfName = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $use + 1, $endOfScope); + + $type = 'class'; + if ($tokens[$startOfName]['code'] === T_STRING) { + $lowerContent = strtolower($tokens[$startOfName]['content']); + if ($lowerContent === 'function' + || $lowerContent === 'const' + ) { + $type = $lowerContent; + + $startOfName = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $startOfName + 1, $endOfScope); + } + } + + $uses[] = [ + 'ptrUse' => $use, + 'name' => trim($phpcsFile->getTokensAsString($startOfName, $endOfScope - $startOfName)), + 'ptrEnd' => $endOfScope, + 'string' => trim($phpcsFile->getTokensAsString($use, $endOfScope - $use + 1)), + 'type' => $type, + ]; + + $start = $endOfScope; + } + + return $uses; + } + + /** + * @param array $a + * @param array $b + * @return int + */ + private function compareUseStatements(array $a, array $b) + { + if ($a['type'] === $b['type']) { + return strnatcasecmp($a['name'], $b['name']); + } + + if ($a['type'] === 'class' + || ($a['type'] === 'function' && $b['type'] === 'const') + ) { + return -1; + } + + return 1; + } + + /** + * @param PHP_CodeSniffer_File $phpcsFile + * @param array[] $uses + * @return void + */ + private function fixAlphabeticalOrder(PHP_CodeSniffer_File $phpcsFile, array $uses) + { + $first = reset($uses); + $last = end($uses); + $lastScopeCloser = $last['ptrEnd']; + + $phpcsFile->fixer->beginChangeset(); + for ($i = $first['ptrUse']; $i <= $lastScopeCloser; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + uasort($uses, function (array $a, array $b) { + return $this->compareUseStatements($a, $b); + }); + + $phpcsFile->fixer->addContent($first['ptrUse'], implode($phpcsFile->eolChar, array_map(function ($use) { + return $use['string']; + }, $uses))); + + $phpcsFile->fixer->endChangeset(); + } +} diff --git a/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php b/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php new file mode 100644 index 00000000..cdc9e1d8 --- /dev/null +++ b/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php @@ -0,0 +1,69 @@ +getTokens(); + $classPtr = $phpcsFile->findNext( + PHP_CodeSniffer_Tokens::$emptyTokens, + $stackPtr + 1, + null, + true + ); + + $lowerContent = strtolower($tokens[$classPtr]['content']); + if ($lowerContent === 'function' || $lowerContent === 'const') { + if ($lowerContent !== $tokens[$classPtr]['content']) { + $error = 'PHP keywords must be lowercase; expected "%s" but found "%s"'; + $data = [$lowerContent, $tokens[$classPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $classPtr, 'NotLowerCase', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($classPtr, $lowerContent); + } + } + + if ($tokens[$classPtr + 1]['code'] !== T_WHITESPACE) { + $error = 'There must be single space after %s keyword'; + $data = [$lowerContent]; + $fix = $phpcsFile->addFixableError($error, $classPtr, 'NoSpace', $data); + + if ($fix) { + $phpcsFile->fixer->addContent($classPtr, ' '); + } + } elseif ($tokens[$classPtr + 1]['content'] !== ' ') { + $error = 'There must be single space after %s keyword'; + $data = [$lowerContent]; + $fix = $phpcsFile->addFixableError($error, $classPtr + 1, 'NoSpace', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($classPtr + 1, ' '); + } + } + } + } +} diff --git a/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php b/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php new file mode 100644 index 00000000..3d0cc60f --- /dev/null +++ b/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php @@ -0,0 +1,64 @@ +getTokens(); + $classPtr = $phpcsFile->findNext( + PHP_CodeSniffer_Tokens::$emptyTokens, + $stackPtr + 1, + null, + true + ); + + $lowerContent = strtolower($tokens[$classPtr]['content']); + if ($lowerContent === 'function' || $lowerContent === 'const') { + $classPtr = $phpcsFile->findNext( + PHP_CodeSniffer_Tokens::$emptyTokens, + $classPtr + 1, + null, + true + ); + } + + if ($tokens[$classPtr]['code'] === T_NS_SEPARATOR + || ($tokens[$classPtr]['code'] === T_STRING + && $tokens[$classPtr]['content'] === '\\') + ) { + $error = 'Use statement cannot start with a backslash'; + $fix = $phpcsFile->addFixableError($error, $classPtr); + + if ($fix) { + if ($tokens[$classPtr - 1]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($classPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken($classPtr, ''); + } + } + } + } +} diff --git a/ZendCodingStandard/Tests/Namespaces/AlphabeticallySortedUsesUnitTest.inc b/ZendCodingStandard/Tests/Namespaces/AlphabeticallySortedUsesUnitTest.inc new file mode 100644 index 00000000..c5f0e920 --- /dev/null +++ b/ZendCodingStandard/Tests/Namespaces/AlphabeticallySortedUsesUnitTest.inc @@ -0,0 +1,27 @@ + 1, + 20 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} diff --git a/ZendCodingStandard/Tests/Namespaces/ConstAndFunctionKeywordsUnitTest.inc b/ZendCodingStandard/Tests/Namespaces/ConstAndFunctionKeywordsUnitTest.inc new file mode 100644 index 00000000..bf2be382 --- /dev/null +++ b/ZendCodingStandard/Tests/Namespaces/ConstAndFunctionKeywordsUnitTest.inc @@ -0,0 +1,7 @@ + 1, + 4 => 1, + 6 => 2, + 7 => 2, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} diff --git a/ZendCodingStandard/Tests/Namespaces/UseDoesNotStartWithBackslashUnitTest.inc b/ZendCodingStandard/Tests/Namespaces/UseDoesNotStartWithBackslashUnitTest.inc new file mode 100644 index 00000000..ce184500 --- /dev/null +++ b/ZendCodingStandard/Tests/Namespaces/UseDoesNotStartWithBackslashUnitTest.inc @@ -0,0 +1,17 @@ + 1, + 5 => 1, + 6 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} diff --git a/ZendCodingStandard/ruleset.xml b/ZendCodingStandard/ruleset.xml old mode 100644 new mode 100755 index 89e0d89b..686f2b1a --- a/ZendCodingStandard/ruleset.xml +++ b/ZendCodingStandard/ruleset.xml @@ -59,10 +59,6 @@ - - - - From ce81157b34898830c6269727ba93c4303fd0b976 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 9 Feb 2017 22:31:01 +0000 Subject: [PATCH 042/225] Added more cases for Classes\UnusedUseStatement sniff --- ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc | 1 + .../Tests/Classes/UnusedUseStatementUnitTest.inc.fixed | 1 + 2 files changed, 2 insertions(+) diff --git a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc index 1bfbffae..0814c6d4 100644 --- a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc +++ b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc @@ -23,6 +23,7 @@ use Used10; use Used11; use FooBar\Used12 as AliasUsed12; use FooBar\Used13; +use Unused6, Unused7; /** * @Used10 diff --git a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed index 52686ba8..be992c36 100644 --- a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed +++ b/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed @@ -17,6 +17,7 @@ use Used10; use Used11; use FooBar\Used12 as AliasUsed12; use FooBar\Used13; +use Unused6, Unused7; /** * @Used10 From c264e18dbc402fc71e0eee57af3623f55f9ca4f4 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 9 Feb 2017 22:32:22 +0000 Subject: [PATCH 043/225] Updated dependencies - use fixed version of PHP_CodeSniffer 2.8.0 - removed slevomat/coding-standard dependency - updated PHPUnit to ^5.7.12 || ^6.0.6 --- composer.json | 5 +- composer.lock | 330 +++++++++++++++++++------------------------------- 2 files changed, 127 insertions(+), 208 deletions(-) diff --git a/composer.json b/composer.json index b51b871f..e02ba5c9 100644 --- a/composer.json +++ b/composer.json @@ -7,11 +7,10 @@ "coding standard" ], "require": { - "squizlabs/php_codesniffer": "^2.7", - "slevomat/coding-standard": "^1.1" + "squizlabs/php_codesniffer": "2.8.0" }, "require-dev": { - "phpunit/phpunit": "^5.6" + "phpunit/phpunit": "^5.7.12 || ^6.0.6" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 093fac00..387b057e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,107 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "24a044053a919e5b2a7acd6f6918468f", - "content-hash": "129ed88cc335edde3c6340c9d15b96ac", + "content-hash": "384f870eccca1b56285bf19a5f22e8a5", "packages": [ - { - "name": "jakub-onderka/php-parallel-lint", - "version": "v0.9.2", - "source": { - "type": "git", - "url": "https://github.com/JakubOnderka/PHP-Parallel-Lint.git", - "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/JakubOnderka/PHP-Parallel-Lint/zipball/2ead2e4043ab125bee9554f356e0a86742c2d4fa", - "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "jakub-onderka/php-console-highlighter": "~0.3", - "nette/tester": "~1.3" - }, - "suggest": { - "jakub-onderka/php-console-highlighter": "Highlight syntax in code snippet" - }, - "bin": [ - "parallel-lint" - ], - "type": "library", - "autoload": { - "classmap": [ - "./" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Jakub Onderka", - "email": "jakub.onderka@gmail.com" - } - ], - "description": "This tool check syntax of PHP files about 20x faster than serial check.", - "homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint", - "time": "2015-12-15 10:42:16" - }, - { - "name": "slevomat/coding-standard", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://github.com/slevomat/coding-standard.git", - "reference": "53c24d3fa620dadc832b6d297f11d908835af97f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/53c24d3fa620dadc832b6d297f11d908835af97f", - "reference": "53c24d3fa620dadc832b6d297f11d908835af97f", - "shasum": "" - }, - "require": { - "jakub-onderka/php-parallel-lint": "^0.9.2", - "php": "^5.6|^7.0", - "squizlabs/php_codesniffer": "^2.6.0" - }, - "require-dev": { - "consistence/coding-standard": "^0.11.0", - "phing/phing": "^2.9", - "phpstan/phpstan": "0.1", - "phpunit/phpunit": "^5.0", - "satooshi/php-coveralls": "^1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "SlevomatCodingStandard\\": "SlevomatCodingStandard" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Slevomat Coding Standard for PHP_CodeSniffer extends Consistence Coding Standard by providing sniffs with additional checks.", - "time": "2016-08-10 15:35:53" - }, { "name": "squizlabs/php_codesniffer", - "version": "2.7.0", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed" + "reference": "86dd55a522238211f9f3631e3361703578941d9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", - "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/86dd55a522238211f9f3631e3361703578941d9a", + "reference": "86dd55a522238211f9f3631e3361703578941d9a", "shasum": "" }, "require": { @@ -169,7 +82,7 @@ "phpcs", "standards" ], - "time": "2016-09-01 23:53:02" + "time": "2017-02-02T03:30:00+00:00" } ], "packages-dev": [ @@ -225,20 +138,20 @@ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.5.5", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108" + "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/399c1f9781e222f6eb6cc238796f5200d1b7f108", - "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5a5a9fc8025a08d8919be87d6884d5a92520cefe", + "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe", "shasum": "" }, "require": { @@ -267,7 +180,7 @@ "object", "object graph" ], - "time": "2016-10-31 17:19:45" + "time": "2017-01-26T22:05:40+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -321,7 +234,7 @@ "reflection", "static analysis" ], - "time": "2015-12-27 11:43:31" + "time": "2015-12-27T11:43:31+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -366,20 +279,20 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-09-30 07:12:33" + "time": "2016-09-30T07:12:33+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.2", + "version": "0.2.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", - "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", "shasum": "" }, "require": { @@ -413,20 +326,20 @@ "email": "me@mikevanriel.com" } ], - "time": "2016-06-10 07:14:17" + "time": "2016-11-25T06:54:22+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.6.1", + "version": "v1.6.2", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "58a8137754bc24b25740d4281399a4a3596058e0" + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", - "reference": "58a8137754bc24b25740d4281399a4a3596058e0", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", "shasum": "" }, "require": { @@ -434,10 +347,11 @@ "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0" + "sebastian/recursion-context": "^1.0|^2.0" }, "require-dev": { - "phpspec/phpspec": "^2.0" + "phpspec/phpspec": "^2.0", + "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", "extra": { @@ -475,20 +389,20 @@ "spy", "stub" ], - "time": "2016-06-07 08:13:47" + "time": "2016-11-21T14:58:47+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "4.0.2", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "6cba06ff75a1a63a71033e1a01b89056f3af1e8d" + "reference": "c19cfc7cbb0e9338d8c469c7eedecc2a428b0971" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6cba06ff75a1a63a71033e1a01b89056f3af1e8d", - "reference": "6cba06ff75a1a63a71033e1a01b89056f3af1e8d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c19cfc7cbb0e9338d8c469c7eedecc2a428b0971", + "reference": "c19cfc7cbb0e9338d8c469c7eedecc2a428b0971", "shasum": "" }, "require": { @@ -538,20 +452,20 @@ "testing", "xunit" ], - "time": "2016-11-01 05:06:24" + "time": "2017-01-20T15:06:43+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", "shasum": "" }, "require": { @@ -585,7 +499,7 @@ "filesystem", "iterator" ], - "time": "2015-06-21 13:08:43" + "time": "2016-10-03T07:40:28+00:00" }, { "name": "phpunit/php-text-template", @@ -626,7 +540,7 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", @@ -670,20 +584,20 @@ "keywords": [ "timer" ], - "time": "2016-05-12 18:03:57" + "time": "2016-05-12T18:03:57+00:00" }, { "name": "phpunit/php-token-stream", - "version": "1.4.8", + "version": "1.4.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", "shasum": "" }, "require": { @@ -719,20 +633,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-09-15 10:49:45" + "time": "2016-11-15T14:06:22+00:00" }, { "name": "phpunit/phpunit", - "version": "5.6.3", + "version": "5.7.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c" + "reference": "944600e244f80a5252679878553b95c63dbf978b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a9de0dbafeb6b1391b391fbb034734cb0af9f67c", - "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/944600e244f80a5252679878553b95c63dbf978b", + "reference": "944600e244f80a5252679878553b95c63dbf978b", "shasum": "" }, "require": { @@ -743,18 +657,18 @@ "ext-xml": "*", "myclabs/deep-copy": "~1.3", "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "^4.0.1", + "phpspec/prophecy": "^1.6.2", + "phpunit/php-code-coverage": "^4.0.4", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "~1.1", + "sebastian/comparator": "^1.2.4", "sebastian/diff": "~1.2", - "sebastian/environment": "^1.3 || ^2.0", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/object-enumerator": "~1.0", + "sebastian/environment": "^1.3.4 || ^2.0", + "sebastian/exporter": "~2.0", + "sebastian/global-state": "^1.1", + "sebastian/object-enumerator": "~2.0", "sebastian/resource-operations": "~1.0", "sebastian/version": "~1.0|~2.0", "symfony/yaml": "~2.1|~3.0" @@ -775,7 +689,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.6.x-dev" + "dev-master": "5.7.x-dev" } }, "autoload": { @@ -801,27 +715,27 @@ "testing", "xunit" ], - "time": "2016-11-14 06:39:40" + "time": "2017-02-08T05:54:05+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.4.0", + "version": "3.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2" + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/238d7a2723bce689c79eeac9c7d5e1d623bb9dc2", - "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.6 || ^7.0", "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2" + "sebastian/exporter": "^1.2 || ^2.0" }, "conflict": { "phpunit/phpunit": "<5.4.0" @@ -860,7 +774,7 @@ "mock", "xunit" ], - "time": "2016-10-09 07:01:45" + "time": "2016-12-08T20:27:08+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -905,26 +819,26 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2016-02-13 06:45:14" + "time": "2016-02-13T06:45:14+00:00" }, { "name": "sebastian/comparator", - "version": "1.2.0", + "version": "1.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2" + "sebastian/exporter": "~1.2 || ~2.0" }, "require-dev": { "phpunit/phpunit": "~4.4" @@ -969,7 +883,7 @@ "compare", "equality" ], - "time": "2015-07-26 15:48:44" + "time": "2017-01-29T09:50:25+00:00" }, { "name": "sebastian/diff", @@ -1021,32 +935,32 @@ "keywords": [ "diff" ], - "time": "2015-12-08 07:14:41" + "time": "2015-12-08T07:14:41+00:00" }, { "name": "sebastian/environment", - "version": "1.3.8", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" + "phpunit/phpunit": "^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1071,25 +985,25 @@ "environment", "hhvm" ], - "time": "2016-08-18 05:49:44" + "time": "2016-11-26T07:53:53+00:00" }, { "name": "sebastian/exporter", - "version": "1.2.2", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", "shasum": "" }, "require": { "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" + "sebastian/recursion-context": "~2.0" }, "require-dev": { "ext-mbstring": "*", @@ -1098,7 +1012,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1138,7 +1052,7 @@ "export", "exporter" ], - "time": "2016-06-17 09:04:28" + "time": "2016-11-19T08:54:04+00:00" }, { "name": "sebastian/global-state", @@ -1189,25 +1103,25 @@ "keywords": [ "global state" ], - "time": "2015-10-12 03:26:01" + "time": "2015-10-12T03:26:01+00:00" }, { "name": "sebastian/object-enumerator", - "version": "1.0.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" + "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", + "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", "shasum": "" }, "require": { "php": ">=5.6", - "sebastian/recursion-context": "~1.0" + "sebastian/recursion-context": "~2.0" }, "require-dev": { "phpunit/phpunit": "~5" @@ -1215,7 +1129,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1235,20 +1149,20 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2016-01-28 13:25:10" + "time": "2016-11-19T07:35:10+00:00" }, { "name": "sebastian/recursion-context", - "version": "1.0.3", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "79860854756415e1cec8d186c9cf261cafd87dfc" + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/79860854756415e1cec8d186c9cf261cafd87dfc", - "reference": "79860854756415e1cec8d186c9cf261cafd87dfc", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", "shasum": "" }, "require": { @@ -1260,7 +1174,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1288,7 +1202,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-11-14 15:54:23" + "time": "2016-11-19T07:33:16+00:00" }, { "name": "sebastian/resource-operations", @@ -1330,20 +1244,20 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28 20:34:47" + "time": "2015-07-28T20:34:47+00:00" }, { "name": "sebastian/version", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5" + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", - "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", "shasum": "" }, "require": { @@ -1373,29 +1287,35 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-02-04 12:56:52" + "time": "2016-10-03T07:35:21+00:00" }, { "name": "symfony/yaml", - "version": "v3.1.6", + "version": "v3.2.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27" + "reference": "e1718c6bf57e1efbb8793ada951584b2ab27775b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/7ff51b06c6c3d5cc6686df69004a42c69df09e27", - "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27", + "url": "https://api.github.com/repos/symfony/yaml/zipball/e1718c6bf57e1efbb8793ada951584b2ab27775b", + "reference": "e1718c6bf57e1efbb8793ada951584b2ab27775b", "shasum": "" }, "require": { "php": ">=5.5.9" }, + "require-dev": { + "symfony/console": "~2.8|~3.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -1422,24 +1342,24 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-10-24 18:41:13" + "time": "2017-01-21T17:06:35+00:00" }, { "name": "webmozart/assert", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "bb2d123231c095735130cc8f6d31385a44c7b308" + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308", - "reference": "bb2d123231c095735130cc8f6d31385a44c7b308", + "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", "shasum": "" }, "require": { - "php": "^5.3.3|^7.0" + "php": "^5.3.3 || ^7.0" }, "require-dev": { "phpunit/phpunit": "^4.6", @@ -1448,7 +1368,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -1472,7 +1392,7 @@ "check", "validate" ], - "time": "2016-08-09 15:02:57" + "time": "2016-11-23T20:04:58+00:00" } ], "aliases": [], From 2f7334a26ce6b40a26837e2d7e172db873a3ce1d Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 9 Feb 2017 22:33:22 +0000 Subject: [PATCH 044/225] Enabled Squiz.WhiteSpace.LanguageConstructSpacing sniff --- ZendCodingStandard/ruleset.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/ZendCodingStandard/ruleset.xml b/ZendCodingStandard/ruleset.xml index 686f2b1a..df78abb8 100755 --- a/ZendCodingStandard/ruleset.xml +++ b/ZendCodingStandard/ruleset.xml @@ -47,6 +47,7 @@ Variable "%s" not allowed in double quoted string; use sprintf() instead. + From 8380db16d45b518a063f19da66962ef11e0049b8 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 9 Feb 2017 22:39:14 +0000 Subject: [PATCH 045/225] Moved sniff "Classes\UnusedUseStatement" to "Namespaces" namespace --- .../Sniffs/{Classes => Namespaces}/UnusedUseStatementSniff.php | 2 +- .../{Classes => Namespaces}/UnusedUseStatementUnitTest.inc | 0 .../UnusedUseStatementUnitTest.inc.fixed | 0 .../{Classes => Namespaces}/UnusedUseStatementUnitTest.php | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename ZendCodingStandard/Sniffs/{Classes => Namespaces}/UnusedUseStatementSniff.php (99%) rename ZendCodingStandard/Tests/{Classes => Namespaces}/UnusedUseStatementUnitTest.inc (100%) rename ZendCodingStandard/Tests/{Classes => Namespaces}/UnusedUseStatementUnitTest.inc.fixed (100%) rename ZendCodingStandard/Tests/{Classes => Namespaces}/UnusedUseStatementUnitTest.php (88%) diff --git a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php b/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php similarity index 99% rename from ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php rename to ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index ed5753ca..4384c236 100644 --- a/ZendCodingStandard/Sniffs/Classes/UnusedUseStatementSniff.php +++ b/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -8,7 +8,7 @@ * * @todo remove once merged to squizlabs/PHP_CodeSniffer (?) */ -namespace ZendCodingStandard\Sniffs\Classes; +namespace ZendCodingStandard\Sniffs\Namespaces; use PHP_CodeSniffer_File; use PHP_CodeSniffer_Sniff; diff --git a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc b/ZendCodingStandard/Tests/Namespaces/UnusedUseStatementUnitTest.inc similarity index 100% rename from ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc rename to ZendCodingStandard/Tests/Namespaces/UnusedUseStatementUnitTest.inc diff --git a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed b/ZendCodingStandard/Tests/Namespaces/UnusedUseStatementUnitTest.inc.fixed similarity index 100% rename from ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.inc.fixed rename to ZendCodingStandard/Tests/Namespaces/UnusedUseStatementUnitTest.inc.fixed diff --git a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.php b/ZendCodingStandard/Tests/Namespaces/UnusedUseStatementUnitTest.php similarity index 88% rename from ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.php rename to ZendCodingStandard/Tests/Namespaces/UnusedUseStatementUnitTest.php index d2f4cf8a..5b763def 100644 --- a/ZendCodingStandard/Tests/Classes/UnusedUseStatementUnitTest.php +++ b/ZendCodingStandard/Tests/Namespaces/UnusedUseStatementUnitTest.php @@ -1,5 +1,5 @@ Date: Wed, 15 Mar 2017 13:55:49 +0000 Subject: [PATCH 046/225] Allow empty lines in arrays Empty lines are allowed in multiline arrays only when the array doesn't have any parents (for example file with configuration) --- ZendCodingStandard/Sniffs/Arrays/FormatSniff.php | 5 ++++- ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc.fixed | 2 ++ ZendCodingStandard/Tests/Arrays/FormatUnitTest.php | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index 7c24c603..2523d4ae 100644 --- a/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -107,7 +107,10 @@ private function multiLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } } } else { - if ($previousLine < $tokens[$next]['line'] - 1) { + if ($previousLine < $tokens[$next]['line'] - 1 + && (! empty($tokens[$stackPtr]['conditions']) + || $previousLine === $tokens[$bracketOpener]['line']) + ) { $firstOnLine = $phpcsFile->findFirstOnLine([], $next, true); $fix = $phpcsFile->addFixableError('Empty line is not allowed here.', $firstOnLine - 1); diff --git a/ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc.fixed b/ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc.fixed index 9626f599..42e3e627 100644 --- a/ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc.fixed +++ b/ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc.fixed @@ -3,11 +3,13 @@ $a1 = ['foo', 'bar']; $a2 = [ 'foo', 'bar', + function() { }, 'elem', new \DateTime(), + // comment ['a', 'b', 'c'], /* comment */ 'val', diff --git a/ZendCodingStandard/Tests/Arrays/FormatUnitTest.php b/ZendCodingStandard/Tests/Arrays/FormatUnitTest.php index f13d3ff7..0ca58686 100644 --- a/ZendCodingStandard/Tests/Arrays/FormatUnitTest.php +++ b/ZendCodingStandard/Tests/Arrays/FormatUnitTest.php @@ -11,10 +11,10 @@ public function getErrorList() 2 => 2, 4 => 1, 5 => 1, - 6 => 1, + // 6 => 1, 7 => 1, 11 => 1, - 12 => 1, + // 12 => 1, 14 => 2, 15 => 1, 16 => 2, From 7aa85c9de788421c81c34083e690b6393dc735e6 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 30 May 2017 18:51:05 +0200 Subject: [PATCH 047/225] Updated to use PHP_CodeSniffer 3.0.0 --- .gitattributes | 1 - composer.json | 12 +- composer.lock | 194 +++++++--------- phpcs.xml | 7 +- phpunit.xml.dist | 7 +- ruleset.xml | 2 +- .../ZendCodingStandard}/CodingStandard.php | 20 +- .../Sniffs/Arrays/FormatSniff.php | 32 +-- .../Sniffs/Arrays/TrailingArrayCommaSniff.php | 13 +- .../AlphabeticallySortedTraitsSniff.php | 22 +- .../Sniffs/Classes/TraitUsageSniff.php | 28 +-- .../Sniffs/Commenting/DocCommentSniff.php | 78 +++---- .../Commenting/FunctionCommentSniff.php | 22 +- .../Commenting/VariableCommentSniff.php | 18 +- .../Sniffs/Formatting/DoubleColonSniff.php | 14 +- .../Sniffs/Formatting/NewKeywordSniff.php | 14 +- .../Formatting/NoSpaceAfterSplatSniff.php | 10 +- .../Sniffs/Methods/LineAfterSniff.php | 23 +- .../AlphabeticallySortedUsesSniff.php | 18 +- .../ConstAndFunctionKeywordsSniff.php | 14 +- .../Namespaces/UnusedUseStatementSniff.php | 16 +- .../UseDoesNotStartWithBackslashSniff.php | 18 +- .../ValidVariableNameSniff.php | 22 +- ...gicalOperatorNotAtTheEndOfTheLineSniff.php | 18 +- .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 42 ++-- .../PHP/InstantiatingParenthesisSniff.php | 18 +- .../Sniffs/PHP/LowerCaseKeywordSniff.php | 4 +- .../Sniffs/PHP/RedundantSemicolonSniff.php | 14 +- .../Sniffs/PHP/TypeCastingSniff.php | 14 +- .../Strings/NoConcatenationAtTheEndSniff.php | 10 +- .../Sniffs/WhiteSpace/BlankLineSniff.php | 12 +- .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 16 +- .../WhiteSpace/NoBlankLineAtStartSniff.php | 12 +- .../ZendCodingStandard}/ruleset.xml | 0 test/Ruleset.php | 16 ++ .../Sniffs}/Arrays/FormatUnitTest.inc | 0 .../Sniffs}/Arrays/FormatUnitTest.inc.fixed | 0 .../Sniffs}/Arrays/FormatUnitTest.php | 4 +- .../Arrays/TrailingArrayCommaUnitTest.inc | 0 .../TrailingArrayCommaUnitTest.inc.fixed | 0 .../Arrays/TrailingArrayCommaUnitTest.php | 4 +- .../AlphabeticallySortedTraitsUnitTest.inc | 0 ...phabeticallySortedTraitsUnitTest.inc.fixed | 0 .../AlphabeticallySortedTraitsUnitTest.php | 4 +- .../Sniffs}/Classes/TraitUsageUnitTest.inc | 0 .../Classes/TraitUsageUnitTest.inc.fixed | 0 .../Sniffs}/Classes/TraitUsageUnitTest.php | 4 +- .../Commenting/DocCommentUnitTest.1.inc | 0 .../Commenting/DocCommentUnitTest.1.inc.fixed | 0 .../Commenting/DocCommentUnitTest.2.inc | 0 .../Commenting/DocCommentUnitTest.2.inc.fixed | 0 .../Commenting/DocCommentUnitTest.3.inc | 0 .../Commenting/DocCommentUnitTest.3.inc.fixed | 0 .../Commenting/DocCommentUnitTest.4.inc | 0 .../Commenting/DocCommentUnitTest.4.inc.fixed | 0 .../Commenting/DocCommentUnitTest.5.inc | 0 .../Commenting/DocCommentUnitTest.5.inc.fixed | 0 .../Commenting/DocCommentUnitTest.6.inc | 0 .../Commenting/DocCommentUnitTest.6.inc.fixed | 0 .../Commenting/DocCommentUnitTest.7.inc | 0 .../Commenting/DocCommentUnitTest.7.inc.fixed | 0 .../Commenting/DocCommentUnitTest.8.inc | 0 .../Commenting/DocCommentUnitTest.8.inc.fixed | 0 .../Commenting/DocCommentUnitTest.9.inc | 0 .../Commenting/DocCommentUnitTest.9.inc.fixed | 0 .../Sniffs}/Commenting/DocCommentUnitTest.inc | 0 .../Commenting/DocCommentUnitTest.inc.fixed | 0 .../Sniffs}/Commenting/DocCommentUnitTest.php | 4 +- .../Formatting/DoubleColonUnitTest.inc | 0 .../Formatting/DoubleColonUnitTest.inc.fixed | 0 .../Formatting/DoubleColonUnitTest.php | 4 +- .../Sniffs}/Formatting/NewKeywordUnitTest.inc | 0 .../Formatting/NewKeywordUnitTest.inc.fixed | 0 .../Sniffs}/Formatting/NewKeywordUnitTest.php | 4 +- .../Formatting/NoSpaceAfterSplatUnitTest.inc | 0 .../NoSpaceAfterSplatUnitTest.inc.fixed | 0 .../Formatting/NoSpaceAfterSplatUnitTest.php | 4 +- .../Sniffs}/Methods/LineAfterUnitTest.1.inc | 0 .../Methods/LineAfterUnitTest.1.inc.fixed | 0 .../Sniffs}/Methods/LineAfterUnitTest.2.inc | 0 .../Methods/LineAfterUnitTest.2.inc.fixed | 0 .../Sniffs}/Methods/LineAfterUnitTest.inc | 0 .../Methods/LineAfterUnitTest.inc.fixed | 0 .../Sniffs}/Methods/LineAfterUnitTest.php | 4 +- .../AlphabeticallySortedUsesUnitTest.inc | 0 ...AlphabeticallySortedUsesUnitTest.inc.fixed | 0 .../AlphabeticallySortedUsesUnitTest.php | 4 +- .../ConstAndFunctionKeywordsUnitTest.inc | 0 ...ConstAndFunctionKeywordsUnitTest.inc.fixed | 0 .../ConstAndFunctionKeywordsUnitTest.php | 4 +- .../Namespaces/UnusedUseStatementUnitTest.inc | 0 .../UnusedUseStatementUnitTest.inc.fixed | 0 .../Namespaces/UnusedUseStatementUnitTest.php | 4 +- .../UseDoesNotStartWithBackslashUnitTest.inc | 0 ...oesNotStartWithBackslashUnitTest.inc.fixed | 0 .../UseDoesNotStartWithBackslashUnitTest.php | 4 +- .../ValidVariableNameUnitTest.inc | 0 .../ValidVariableNameUnitTest.php | 4 +- ...alOperatorNotAtTheEndOfTheLineUnitTest.inc | 0 ...atorNotAtTheEndOfTheLineUnitTest.inc.fixed | 0 ...alOperatorNotAtTheEndOfTheLineUnitTest.php | 4 +- .../PHP/CorrectClassNameCaseUnitTest.1.inc | 0 .../CorrectClassNameCaseUnitTest.1.inc.fixed | 0 .../PHP/CorrectClassNameCaseUnitTest.inc | 6 +- .../CorrectClassNameCaseUnitTest.inc.fixed | 6 +- .../PHP/CorrectClassNameCaseUnitTest.php | 4 +- .../PHP/InstantiatingParenthesisUnitTest.inc | 0 ...InstantiatingParenthesisUnitTest.inc.fixed | 0 .../PHP/InstantiatingParenthesisUnitTest.php | 4 +- .../Sniffs}/PHP/LowerCaseKeywordUnitTest.inc | 0 .../PHP/LowerCaseKeywordUnitTest.inc.fixed | 0 .../Sniffs}/PHP/LowerCaseKeywordUnitTest.php | 4 +- .../PHP/RedundantSemicolonUnitTest.inc | 0 .../PHP/RedundantSemicolonUnitTest.inc.fixed | 0 .../PHP/RedundantSemicolonUnitTest.php | 4 +- .../Sniffs}/PHP/TypeCastingUnitTest.inc | 0 .../Sniffs}/PHP/TypeCastingUnitTest.inc.fixed | 0 .../Sniffs}/PHP/TypeCastingUnitTest.php | 4 +- .../NoConcatenationAtTheEndUnitTest.inc | 0 .../NoConcatenationAtTheEndUnitTest.inc.fixed | 0 .../NoConcatenationAtTheEndUnitTest.php | 4 +- .../Tests => test/Sniffs}/TestCase.php | 213 +++++++++++------- .../Sniffs}/WhiteSpace/BlankLineUnitTest.inc | 0 .../WhiteSpace/BlankLineUnitTest.inc.fixed | 0 .../Sniffs}/WhiteSpace/BlankLineUnitTest.php | 4 +- .../WhiteSpace/CommaSpacingUnitTest.inc | 0 .../WhiteSpace/CommaSpacingUnitTest.inc.fixed | 0 .../WhiteSpace/CommaSpacingUnitTest.php | 4 +- .../WhiteSpace/NoBlankLineAtStartUnitTest.inc | 0 .../NoBlankLineAtStartUnitTest.inc.fixed | 0 .../WhiteSpace/NoBlankLineAtStartUnitTest.php | 4 +- 131 files changed, 576 insertions(+), 526 deletions(-) rename {ZendCodingStandard => src/ZendCodingStandard}/CodingStandard.php (81%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Arrays/FormatSniff.php (92%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Arrays/TrailingArrayCommaSniff.php (87%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php (85%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Classes/TraitUsageSniff.php (92%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Commenting/DocCommentSniff.php (92%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Commenting/FunctionCommentSniff.php (97%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Commenting/VariableCommentSniff.php (88%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Formatting/DoubleColonSniff.php (80%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Formatting/NewKeywordSniff.php (79%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Formatting/NoSpaceAfterSplatSniff.php (72%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Methods/LineAfterSniff.php (71%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php (88%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php (85%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Namespaces/UnusedUseStatementSniff.php (94%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php (79%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/NamingConventions/ValidVariableNameSniff.php (70%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php (76%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/PHP/CorrectClassNameCaseSniff.php (88%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/PHP/InstantiatingParenthesisSniff.php (72%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/PHP/LowerCaseKeywordSniff.php (63%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/PHP/RedundantSemicolonSniff.php (78%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/PHP/TypeCastingSniff.php (90%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/Strings/NoConcatenationAtTheEndSniff.php (77%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/WhiteSpace/BlankLineSniff.php (73%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/WhiteSpace/CommaSpacingSniff.php (88%) rename {ZendCodingStandard => src/ZendCodingStandard}/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php (84%) rename {ZendCodingStandard => src/ZendCodingStandard}/ruleset.xml (100%) create mode 100644 test/Ruleset.php rename {ZendCodingStandard/Tests => test/Sniffs}/Arrays/FormatUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Arrays/FormatUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Arrays/FormatUnitTest.php (90%) rename {ZendCodingStandard/Tests => test/Sniffs}/Arrays/TrailingArrayCommaUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Arrays/TrailingArrayCommaUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Arrays/TrailingArrayCommaUnitTest.php (75%) rename {ZendCodingStandard/Tests => test/Sniffs}/Classes/AlphabeticallySortedTraitsUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Classes/AlphabeticallySortedTraitsUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Classes/AlphabeticallySortedTraitsUnitTest.php (73%) rename {ZendCodingStandard/Tests => test/Sniffs}/Classes/TraitUsageUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Classes/TraitUsageUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Classes/TraitUsageUnitTest.php (80%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.1.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.1.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.2.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.2.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.3.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.3.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.4.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.4.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.5.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.5.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.6.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.6.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.7.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.7.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.8.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.8.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.9.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.9.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Commenting/DocCommentUnitTest.php (97%) rename {ZendCodingStandard/Tests => test/Sniffs}/Formatting/DoubleColonUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Formatting/DoubleColonUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Formatting/DoubleColonUnitTest.php (81%) rename {ZendCodingStandard/Tests => test/Sniffs}/Formatting/NewKeywordUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Formatting/NewKeywordUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Formatting/NewKeywordUnitTest.php (81%) rename {ZendCodingStandard/Tests => test/Sniffs}/Formatting/NoSpaceAfterSplatUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Formatting/NoSpaceAfterSplatUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Formatting/NoSpaceAfterSplatUnitTest.php (80%) rename {ZendCodingStandard/Tests => test/Sniffs}/Methods/LineAfterUnitTest.1.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Methods/LineAfterUnitTest.1.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Methods/LineAfterUnitTest.2.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Methods/LineAfterUnitTest.2.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Methods/LineAfterUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Methods/LineAfterUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Methods/LineAfterUnitTest.php (90%) rename {ZendCodingStandard/Tests => test/Sniffs}/Namespaces/AlphabeticallySortedUsesUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Namespaces/AlphabeticallySortedUsesUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Namespaces/AlphabeticallySortedUsesUnitTest.php (74%) rename {ZendCodingStandard/Tests => test/Sniffs}/Namespaces/ConstAndFunctionKeywordsUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Namespaces/ConstAndFunctionKeywordsUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Namespaces/ConstAndFunctionKeywordsUnitTest.php (76%) rename {ZendCodingStandard/Tests => test/Sniffs}/Namespaces/UnusedUseStatementUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Namespaces/UnusedUseStatementUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Namespaces/UnusedUseStatementUnitTest.php (77%) rename {ZendCodingStandard/Tests => test/Sniffs}/Namespaces/UseDoesNotStartWithBackslashUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Namespaces/UseDoesNotStartWithBackslashUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Namespaces/UseDoesNotStartWithBackslashUnitTest.php (76%) rename {ZendCodingStandard/Tests => test/Sniffs}/NamingConventions/ValidVariableNameUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/NamingConventions/ValidVariableNameUnitTest.php (74%) rename {ZendCodingStandard/Tests => test/Sniffs}/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.php (80%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/CorrectClassNameCaseUnitTest.1.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/CorrectClassNameCaseUnitTest.1.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/CorrectClassNameCaseUnitTest.inc (88%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/CorrectClassNameCaseUnitTest.inc.fixed (88%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/CorrectClassNameCaseUnitTest.php (91%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/InstantiatingParenthesisUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/InstantiatingParenthesisUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/InstantiatingParenthesisUnitTest.php (85%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/LowerCaseKeywordUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/LowerCaseKeywordUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/LowerCaseKeywordUnitTest.php (92%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/RedundantSemicolonUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/RedundantSemicolonUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/RedundantSemicolonUnitTest.php (78%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/TypeCastingUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/TypeCastingUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/PHP/TypeCastingUnitTest.php (89%) rename {ZendCodingStandard/Tests => test/Sniffs}/Strings/NoConcatenationAtTheEndUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Strings/NoConcatenationAtTheEndUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/Strings/NoConcatenationAtTheEndUnitTest.php (75%) rename {ZendCodingStandard/Tests => test/Sniffs}/TestCase.php (62%) rename {ZendCodingStandard/Tests => test/Sniffs}/WhiteSpace/BlankLineUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/WhiteSpace/BlankLineUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/WhiteSpace/BlankLineUnitTest.php (78%) rename {ZendCodingStandard/Tests => test/Sniffs}/WhiteSpace/CommaSpacingUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/WhiteSpace/CommaSpacingUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/WhiteSpace/CommaSpacingUnitTest.php (84%) rename {ZendCodingStandard/Tests => test/Sniffs}/WhiteSpace/NoBlankLineAtStartUnitTest.inc (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/WhiteSpace/NoBlankLineAtStartUnitTest.inc.fixed (100%) rename {ZendCodingStandard/Tests => test/Sniffs}/WhiteSpace/NoBlankLineAtStartUnitTest.php (82%) diff --git a/.gitattributes b/.gitattributes index 4914e2e1..2ff2155b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,3 @@ -/ZendCodingStandard/Tests export-ignore .coveralls.yml .gitattributes export-ignore .gitignore export-ignore diff --git a/composer.json b/composer.json index e02ba5c9..f756fada 100644 --- a/composer.json +++ b/composer.json @@ -7,19 +7,23 @@ "coding standard" ], "require": { - "squizlabs/php_codesniffer": "2.8.0" + "squizlabs/php_codesniffer": "3.0.0" }, "require-dev": { - "phpunit/phpunit": "^5.7.12 || ^6.0.6" + "phpunit/phpunit": "^6.1.4 || ^5.7.20" }, "autoload": { "psr-4": { - "ZendCodingStandard\\Sniffs\\": "ZendCodingStandard/Sniffs" + "ZendCodingStandard\\": "src/ZendCodingStandard/" } }, "autoload-dev": { + "files": [ + "vendor/squizlabs/php_codesniffer/autoload.php" + ], "psr-4": { - "ZendCodingStandard\\Tests\\": "ZendCodingStandard/Tests" + "PHP_CodeSniffer\\": "vendor/squizlabs/php_codesniffer/src/", + "ZendCodingStandardTest\\": "test/" } }, "scripts": { diff --git a/composer.lock b/composer.lock index 387b057e..a940f9da 100644 --- a/composer.lock +++ b/composer.lock @@ -4,68 +4,41 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "384f870eccca1b56285bf19a5f22e8a5", + "content-hash": "43a686d3157db48ed076a5092e66e526", "packages": [ { "name": "squizlabs/php_codesniffer", - "version": "2.8.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "86dd55a522238211f9f3631e3361703578941d9a" + "reference": "b95ff2c3b122a3ee4b57d149a57d2afce65522c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/86dd55a522238211f9f3631e3361703578941d9a", - "reference": "86dd55a522238211f9f3631e3361703578941d9a", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/b95ff2c3b122a3ee4b57d149a57d2afce65522c3", + "reference": "b95ff2c3b122a3ee4b57d149a57d2afce65522c3", "shasum": "" }, "require": { "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": ">=5.1.2" + "php": ">=5.4.0" }, "require-dev": { "phpunit/phpunit": "~4.0" }, "bin": [ - "scripts/phpcs", - "scripts/phpcbf" + "bin/phpcs", + "bin/phpcbf" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "3.x-dev" } }, - "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -82,7 +55,7 @@ "phpcs", "standards" ], - "time": "2017-02-02T03:30:00+00:00" + "time": "2017-05-04T00:33:04+00:00" } ], "packages-dev": [ @@ -142,16 +115,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.6.0", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe" + "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5a5a9fc8025a08d8919be87d6884d5a92520cefe", - "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8e6e04167378abf1ddb4d3522d8755c5fd90d102", + "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102", "shasum": "" }, "require": { @@ -180,7 +153,7 @@ "object", "object graph" ], - "time": "2017-01-26T22:05:40+00:00" + "time": "2017-04-12T18:52:22+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -330,27 +303,27 @@ }, { "name": "phpspec/prophecy", - "version": "v1.6.2", + "version": "v1.7.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0|^2.0" + "sebastian/comparator": "^1.1|^2.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { - "phpspec/phpspec": "^2.0", + "phpspec/phpspec": "^2.5|^3.2", "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", @@ -389,39 +362,39 @@ "spy", "stub" ], - "time": "2016-11-21T14:58:47+00:00" + "time": "2017-03-02T20:05:34+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "4.0.5", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "c19cfc7cbb0e9338d8c469c7eedecc2a428b0971" + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c19cfc7cbb0e9338d8c469c7eedecc2a428b0971", - "reference": "c19cfc7cbb0e9338d8c469c7eedecc2a428b0971", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", "shasum": "" }, "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", "php": "^5.6 || ^7.0", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "^1.4.2", - "sebastian/code-unit-reverse-lookup": "~1.0", + "phpunit/php-file-iterator": "^1.3", + "phpunit/php-text-template": "^1.2", + "phpunit/php-token-stream": "^1.4.2 || ^2.0", + "sebastian/code-unit-reverse-lookup": "^1.0", "sebastian/environment": "^1.3.2 || ^2.0", - "sebastian/version": "~1.0|~2.0" + "sebastian/version": "^1.0 || ^2.0" }, "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "^5.4" + "ext-xdebug": "^2.1.4", + "phpunit/phpunit": "^5.7" }, "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.4.0", - "ext-xmlwriter": "*" + "ext-xdebug": "^2.5.1" }, "type": "library", "extra": { @@ -452,7 +425,7 @@ "testing", "xunit" ], - "time": "2017-01-20T15:06:43+00:00" + "time": "2017-04-02T07:44:40+00:00" }, { "name": "phpunit/php-file-iterator", @@ -544,25 +517,30 @@ }, { "name": "phpunit/php-timer", - "version": "1.0.8", + "version": "1.0.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4|~5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -584,20 +562,20 @@ "keywords": [ "timer" ], - "time": "2016-05-12T18:03:57+00:00" + "time": "2017-02-26T11:10:40+00:00" }, { "name": "phpunit/php-token-stream", - "version": "1.4.9", + "version": "1.4.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", "shasum": "" }, "require": { @@ -633,20 +611,20 @@ "keywords": [ "tokenizer" ], - "time": "2016-11-15T14:06:22+00:00" + "time": "2017-02-27T10:12:30+00:00" }, { "name": "phpunit/phpunit", - "version": "5.7.12", + "version": "5.7.20", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "944600e244f80a5252679878553b95c63dbf978b" + "reference": "3cb94a5f8c07a03c8b7527ed7468a2926203f58b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/944600e244f80a5252679878553b95c63dbf978b", - "reference": "944600e244f80a5252679878553b95c63dbf978b", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3cb94a5f8c07a03c8b7527ed7468a2926203f58b", + "reference": "3cb94a5f8c07a03c8b7527ed7468a2926203f58b", "shasum": "" }, "require": { @@ -664,13 +642,13 @@ "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "^3.2", "sebastian/comparator": "^1.2.4", - "sebastian/diff": "~1.2", + "sebastian/diff": "^1.4.3", "sebastian/environment": "^1.3.4 || ^2.0", "sebastian/exporter": "~2.0", "sebastian/global-state": "^1.1", "sebastian/object-enumerator": "~2.0", "sebastian/resource-operations": "~1.0", - "sebastian/version": "~1.0|~2.0", + "sebastian/version": "~1.0.3|~2.0", "symfony/yaml": "~2.1|~3.0" }, "conflict": { @@ -715,7 +693,7 @@ "testing", "xunit" ], - "time": "2017-02-08T05:54:05+00:00" + "time": "2017-05-22T07:42:55+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -778,23 +756,23 @@ }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", - "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", "shasum": "" }, "require": { - "php": ">=5.6" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~5" + "phpunit/phpunit": "^5.7 || ^6.0" }, "type": "library", "extra": { @@ -819,7 +797,7 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2016-02-13T06:45:14+00:00" + "time": "2017-03-04T06:30:41+00:00" }, { "name": "sebastian/comparator", @@ -887,23 +865,23 @@ }, { "name": "sebastian/diff", - "version": "1.4.1", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.8" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", "extra": { @@ -935,7 +913,7 @@ "keywords": [ "diff" ], - "time": "2015-12-08T07:14:41+00:00" + "time": "2017-05-22T07:24:03+00:00" }, { "name": "sebastian/environment", @@ -1107,16 +1085,16 @@ }, { "name": "sebastian/object-enumerator", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35" + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", - "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", "shasum": "" }, "require": { @@ -1149,7 +1127,7 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2016-11-19T07:35:10+00:00" + "time": "2017-02-18T15:18:39+00:00" }, { "name": "sebastian/recursion-context", @@ -1291,16 +1269,16 @@ }, { "name": "symfony/yaml", - "version": "v3.2.3", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "e1718c6bf57e1efbb8793ada951584b2ab27775b" + "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/e1718c6bf57e1efbb8793ada951584b2ab27775b", - "reference": "e1718c6bf57e1efbb8793ada951584b2ab27775b", + "url": "https://api.github.com/repos/symfony/yaml/zipball/acec26fcf7f3031e094e910b94b002fa53d4e4d6", + "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6", "shasum": "" }, "require": { @@ -1342,7 +1320,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-01-21T17:06:35+00:00" + "time": "2017-05-01T14:55:58+00:00" }, { "name": "webmozart/assert", diff --git a/phpcs.xml b/phpcs.xml index a7e3a986..f7d0b9fa 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -1,8 +1,9 @@ - + - ZendCodingStandard + src + test - */Tests/*.inc + test/*.inc diff --git a/phpunit.xml.dist b/phpunit.xml.dist index e36b0911..1d3a2ed2 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -2,15 +2,12 @@ - ./ZendCodingStandard/Tests + ./test - ./ZendCodingStandard - - ./ZendCodingStandard/Tests - + ./src diff --git a/ruleset.xml b/ruleset.xml index 174cd238..35c6319a 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -1,4 +1,4 @@ - + diff --git a/ZendCodingStandard/CodingStandard.php b/src/ZendCodingStandard/CodingStandard.php similarity index 81% rename from ZendCodingStandard/CodingStandard.php rename to src/ZendCodingStandard/CodingStandard.php index b3d17080..75d2fff7 100644 --- a/ZendCodingStandard/CodingStandard.php +++ b/src/ZendCodingStandard/CodingStandard.php @@ -1,9 +1,9 @@ getTokens(); // Ignore USE keywords inside closures. - $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { return false; } @@ -90,16 +90,16 @@ public static function isTraitUse(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr * @return bool */ - public static function isGlobalUse(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + public static function isGlobalUse(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); // Ignore USE keywords inside closures. - $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { return false; } diff --git a/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php similarity index 92% rename from ZendCodingStandard/Sniffs/Arrays/FormatSniff.php rename to src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index 2523d4ae..1c6a6863 100644 --- a/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -1,10 +1,10 @@ getTokens(); $arrayToken = $tokens[$stackPtr]; @@ -43,11 +43,11 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr * @return void */ - private function multiLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + private function multiLineArray(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $arrayToken = $tokens[$stackPtr]; @@ -58,7 +58,7 @@ private function multiLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $firstContent = $phpcsFile->findNext(T_WHITESPACE, $bracketOpener + 1, null, true); if ($tokens[$firstContent]['code'] === T_CLOSE_SHORT_ARRAY) { $error = 'Empty array must be in one line.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr); + $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); if ($fix) { $phpcsFile->fixer->replaceToken($bracketOpener + 1, ''); @@ -70,7 +70,7 @@ private function multiLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $bracketCloser - 1, null, true); if ($tokens[$bracketCloser]['line'] > $tokens[$lastContent]['line'] + 1) { $error = 'Blank line found at the end of array'; - $fix = $phpcsFile->addFixableError($error, $bracketCloser - 1); + $fix = $phpcsFile->addFixableError($error, $bracketCloser - 1, ''); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -95,7 +95,7 @@ private function multiLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) if ($previousLine === $tokens[$next]['line']) { if ($tokens[$next]['code'] !== T_COMMENT) { $error = 'There must be one array element per line.'; - $fix = $phpcsFile->addFixableError($error, $next); + $fix = $phpcsFile->addFixableError($error, $next, ''); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -113,7 +113,7 @@ private function multiLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) ) { $firstOnLine = $phpcsFile->findFirstOnLine([], $next, true); - $fix = $phpcsFile->addFixableError('Empty line is not allowed here.', $firstOnLine - 1); + $fix = $phpcsFile->addFixableError('Empty line is not allowed here.', $firstOnLine - 1, ''); if ($fix) { $phpcsFile->fixer->replaceToken($firstOnLine - 1, ''); @@ -166,7 +166,7 @@ private function multiLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) if ($first = $phpcsFile->findFirstOnLine([], $bracketCloser, true)) { if ($first < $bracketCloser - 1) { $error = 'Array closing bracket should be in new line.'; - $fix = $phpcsFile->addFixableError($error, $bracketCloser); + $fix = $phpcsFile->addFixableError($error, $bracketCloser, ''); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -181,11 +181,11 @@ private function multiLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr * @return void */ - private function singleLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + private function singleLineArray(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $arrayToken = $tokens[$stackPtr]; @@ -200,7 +200,7 @@ private function singleLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) strlen($tokens[$bracketOpener + 1]['content']) ); - $fix = $phpcsFile->addFixableError($error, $bracketOpener + 1); + $fix = $phpcsFile->addFixableError($error, $bracketOpener + 1, ''); if ($fix) { $phpcsFile->fixer->replaceToken($bracketOpener + 1, ''); @@ -214,7 +214,7 @@ private function singleLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr) strlen($tokens[$bracketCloser - 1]['content']) ); - $fix = $phpcsFile->addFixableError($error, $bracketCloser - 1); + $fix = $phpcsFile->addFixableError($error, $bracketCloser - 1, ''); if ($fix) { $phpcsFile->fixer->replaceToken($bracketCloser - 1, ''); diff --git a/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php similarity index 87% rename from ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php rename to src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php index a68987da..66147055 100644 --- a/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php @@ -5,10 +5,10 @@ */ namespace ZendCodingStandard\Sniffs\Arrays; -use PHP_CodeSniffer_File; -use PHP_CodeSniffer_Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; -class TrailingArrayCommaSniff implements PHP_CodeSniffer_Sniff +class TrailingArrayCommaSniff implements Sniff { /** * @return int[] @@ -19,11 +19,11 @@ public function register() } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr * @return void */ - public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + public function process(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $arrayToken = $tokens[$stackPtr]; @@ -60,7 +60,8 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) ) { $fix = $phpcsFile->addFixableError( 'Multiline arrays must have a trailing comma after the last element', - $previousToCloseParenthesisPointer + $previousToCloseParenthesisPointer, + '' ); if ($fix) { diff --git a/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php similarity index 85% rename from ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php rename to src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php index 810197f7..6066a9ec 100644 --- a/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php @@ -1,11 +1,11 @@ getTraits($phpcsFile, $stackPtr); @@ -50,11 +50,11 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $scopePtr * @return array[] */ - private function getTraits(PHP_CodeSniffer_File $phpcsFile, $scopePtr) + private function getTraits(File $phpcsFile, $scopePtr) { $tokens = $phpcsFile->getTokens(); @@ -94,11 +94,11 @@ private function getTraits(PHP_CodeSniffer_File $phpcsFile, $scopePtr) } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr * @return int */ - private function getEndOfTraitScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + private function getEndOfTraitScope(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); @@ -124,11 +124,11 @@ private function compareUseStatements(array $a, array $b) } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param array[] $uses * @return void */ - private function fixAlphabeticalOrder(PHP_CodeSniffer_File $phpcsFile, array $uses) + private function fixAlphabeticalOrder(File $phpcsFile, array $uses) { $first = reset($uses); $last = end($uses); diff --git a/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php similarity index 92% rename from ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php rename to src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php index 0f3aaa37..3043137a 100644 --- a/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php @@ -1,12 +1,12 @@ findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$prev]['line'] + 1 !== $tokens[$stackPtr]['line']) { $error = 'Blank line is not allowed before trait declaration'; - $fix = $phpcsFile->addFixableError($error, $stackPtr); + $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -68,7 +68,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $comma = $phpcsFile->findNext(T_COMMA, $stackPtr + 1, $scopeOpener - 1); if ($comma) { $error = 'There must be one USE per declaration.'; - $fix = $phpcsFile->addFixableError($error, $comma); + $fix = $phpcsFile->addFixableError($error, $comma, ''); if ($fix) { $phpcsFile->fixer->replaceToken($comma, ';' . $phpcsFile->eolChar . 'use '); @@ -91,7 +91,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) if ($firstNotEmpty !== $lastNotEmpty) { $emptyInName = $phpcsFile->findNext( - PHP_CodeSniffer_Tokens::$emptyTokens, + Tokens::$emptyTokens, $firstNotEmpty + 1, $lastNotEmpty ); @@ -108,7 +108,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) if ($tokens[$scopeOpener]['code'] === T_OPEN_CURLY_BRACKET) { $prevNonEmpty = $phpcsFile->findPrevious( - PHP_CodeSniffer_Tokens::$emptyTokens, + Tokens::$emptyTokens, $scopeOpener - 1, null, true @@ -138,10 +138,10 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } } - $nextNonEmpty = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $scopeOpener + 1, null, true); + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $scopeOpener + 1, null, true); if ($tokens[$nextNonEmpty]['line'] !== $tokens[$scopeOpener]['line'] + 1) { $error = 'Content must be in next line after opening curly bracket.'; - $fix = $phpcsFile->addFixableError($error, $scopeOpener); + $fix = $phpcsFile->addFixableError($error, $scopeOpener, ''); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -155,14 +155,14 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $scopeCloser = $tokens[$scopeOpener]['scope_closer']; $prevNonEmpty = $phpcsFile->findPrevious( - PHP_CodeSniffer_Tokens::$emptyTokens, + Tokens::$emptyTokens, $scopeCloser - 1, null, true ); if ($tokens[$prevNonEmpty]['line'] + 1 !== $tokens[$scopeCloser]['line']) { $error = 'Close curly bracket must be in next line after content.'; - $fix = $phpcsFile->addFixableError($error, $scopeCloser); + $fix = $phpcsFile->addFixableError($error, $scopeCloser, ''); if ($fix) { $phpcsFile->fixer->beginChangeset(); diff --git a/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php similarity index 92% rename from ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php rename to src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index b31aae85..e3c00386 100644 --- a/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -1,10 +1,10 @@ getTokens(); $commentStart = $stackPtr; @@ -50,12 +50,12 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) /** * Checks if doc comment is empty. * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $commentStart * @param int $commentEnd * @return bool */ - private function checkIfEmpty(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) + private function checkIfEmpty(File $phpcsFile, $commentStart, $commentEnd) { $tokens = $phpcsFile->getTokens(); @@ -116,18 +116,18 @@ private function checkIfEmpty(PHP_CodeSniffer_File $phpcsFile, $commentStart, $c * Checks if there is no any other content before doc comment opening tag, * and if there is blank line before doc comment (for multiline doc comment). * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $commentStart * @return void */ - private function checkBeforeOpen(PHP_CodeSniffer_File $phpcsFile, $commentStart) + private function checkBeforeOpen(File $phpcsFile, $commentStart) { $tokens = $phpcsFile->getTokens(); $previous = $phpcsFile->findPrevious(T_WHITESPACE, $commentStart - 1, null, true); if ($tokens[$previous]['line'] === $tokens[$commentStart]['line']) { $error = 'The open comment tag must be the only content on the line.'; - $fix = $phpcsFile->addFixableError($error, $commentStart); + $fix = $phpcsFile->addFixableError($error, $commentStart, ''); if ($fix) { $nonEmpty = $phpcsFile->findPrevious(T_WHITESPACE, $commentStart - 1, null, true); @@ -145,7 +145,7 @@ private function checkBeforeOpen(PHP_CodeSniffer_File $phpcsFile, $commentStart) && $tokens[$previous]['code'] !== T_OPEN_CURLY_BRACKET ) { $error = 'Missing blank line before doc comment.'; - $fix = $phpcsFile->addFixableError($error, $commentStart); + $fix = $phpcsFile->addFixableError($error, $commentStart, ''); if ($fix) { $phpcsFile->fixer->addNewlineBefore($commentStart); @@ -156,18 +156,18 @@ private function checkBeforeOpen(PHP_CodeSniffer_File $phpcsFile, $commentStart) /** * Checks if there is no any other content after doc comment opening tag (for multiline doc comment). * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $commentStart * @return void */ - private function checkAfterOpen(PHP_CodeSniffer_File $phpcsFile, $commentStart) + private function checkAfterOpen(File $phpcsFile, $commentStart) { $tokens = $phpcsFile->getTokens(); $next = $phpcsFile->findNext(T_DOC_COMMENT_WHITESPACE, $commentStart + 1, null, true); if ($tokens[$next]['line'] === $tokens[$commentStart]['line']) { $error = 'The open comment tag must be the only content on the line.'; - $fix = $phpcsFile->addFixableError($error, $commentStart); + $fix = $phpcsFile->addFixableError($error, $commentStart, ''); if ($fix) { $indentToken = $tokens[$commentStart - 1]; @@ -195,18 +195,18 @@ private function checkAfterOpen(PHP_CodeSniffer_File $phpcsFile, $commentStart) /** * Checks if there is no any other content before doc comment closing tag (for multiline doc comment). * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $commentEnd * @return void */ - private function checkBeforeClose(PHP_CodeSniffer_File $phpcsFile, $commentEnd) + private function checkBeforeClose(File $phpcsFile, $commentEnd) { $tokens = $phpcsFile->getTokens(); $previous = $phpcsFile->findPrevious(T_DOC_COMMENT_WHITESPACE, $commentEnd - 1, null, true); if ($tokens[$previous]['line'] === $tokens[$commentEnd]['line']) { $error = 'The close comment tag must be the only content on the line.'; - $fix = $phpcsFile->addFixableError($error, $commentEnd); + $fix = $phpcsFile->addFixableError($error, $commentEnd, ''); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -223,12 +223,12 @@ private function checkBeforeClose(PHP_CodeSniffer_File $phpcsFile, $commentEnd) /** * Checks if there is no any other content after doc comment closing tag (for multiline doc comment). * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $commentStart * @param int $commentEnd * @return void */ - private function checkAfterClose(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) + private function checkAfterClose(File $phpcsFile, $commentStart, $commentEnd) { $tokens = $phpcsFile->getTokens(); @@ -241,13 +241,13 @@ private function checkAfterClose(PHP_CodeSniffer_File $phpcsFile, $commentStart, if (! $next) { $error = 'Doc comment is not allowed at the end of the file.'; - $phpcsFile->addError($error, $commentStart); + $phpcsFile->addError($error, $commentStart, ''); return; } if ($tokens[$commentEnd]['line'] === $tokens[$next]['line']) { $error = 'The close comment tag must be the only content on the line.'; - $fix = $phpcsFile->addFixableError($error, $commentEnd); + $fix = $phpcsFile->addFixableError($error, $commentEnd, ''); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -283,12 +283,12 @@ private function checkAfterClose(PHP_CodeSniffer_File $phpcsFile, $commentStart, * Checks if there is exactly one space after doc comment opening tag, * and exactly one space before closing tag (for single line doc comment). * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $commentStart * @param int $commentEnd * @return void */ - private function checkSpacesInOneLineComment(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) + private function checkSpacesInOneLineComment(File $phpcsFile, $commentStart, $commentEnd) { $tokens = $phpcsFile->getTokens(); @@ -297,7 +297,7 @@ private function checkSpacesInOneLineComment(PHP_CodeSniffer_File $phpcsFile, $c && $tokens[$commentStart + 1]['content'] !== ' ' ) { $error = 'Expected 1 space after opening tag of one line doc block comment.'; - $fix = $phpcsFile->addFixableError($error, $commentStart + 1); + $fix = $phpcsFile->addFixableError($error, $commentStart + 1, ''); if ($fix) { $phpcsFile->fixer->replaceToken($commentStart + 1, ' '); @@ -306,7 +306,7 @@ private function checkSpacesInOneLineComment(PHP_CodeSniffer_File $phpcsFile, $c // This case is currently not supported. // Comment /**@var null $name; */ is not recognized as doc-block comment. $error = 'Expected 1 space after opening tag of one line doc block comment.'; - $fix = $phpcsFile->addFixableError($error, $commentStart); + $fix = $phpcsFile->addFixableError($error, $commentStart, ''); if ($fix) { $phpcsFile->fixer->addContent($commentStart, ' '); @@ -317,7 +317,7 @@ private function checkSpacesInOneLineComment(PHP_CodeSniffer_File $phpcsFile, $c $content = $tokens[$commentEnd - 1]['content']; if (trim($content) . ' ' !== $content) { $error = 'Expected 1 space before closing tag of one line doc block comment.'; - $fix = $phpcsFile->addFixableError($error, $commentEnd - 1); + $fix = $phpcsFile->addFixableError($error, $commentEnd - 1, ''); if ($fix) { $phpcsFile->fixer->replaceToken($commentEnd - 1, trim($content) . ' '); @@ -331,12 +331,12 @@ private function checkSpacesInOneLineComment(PHP_CodeSniffer_File $phpcsFile, $c * * TODO: needs to check with doctrine annotations * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $commentStart * @param int $commentEnd * @return void */ - private function checkSpacesAfterStar(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) + private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEnd) { $tokens = $phpcsFile->getTokens(); @@ -350,7 +350,7 @@ private function checkSpacesAfterStar(PHP_CodeSniffer_File $phpcsFile, $commentS ) { if ($tokens[$next + 1]['code'] !== T_DOC_COMMENT_WHITESPACE) { $error = 'There must be exactly one space between star and comment.'; - $fix = $phpcsFile->addFixableError($error, $next); + $fix = $phpcsFile->addFixableError($error, $next, ''); if ($fix) { $phpcsFile->fixer->addContent($next, ' '); @@ -360,7 +360,7 @@ private function checkSpacesAfterStar(PHP_CodeSniffer_File $phpcsFile, $commentS || $tokens[$next + 1]['line'] === $tokens[$commentStart]['line'] + 1) ) { $error = 'There must be exactly one space between star and comment.'; - $fix = $phpcsFile->addFixableError($error, $next + 1); + $fix = $phpcsFile->addFixableError($error, $next + 1, ''); if ($fix) { $phpcsFile->fixer->replaceToken($next + 1, ' '); @@ -374,12 +374,12 @@ private function checkSpacesAfterStar(PHP_CodeSniffer_File $phpcsFile, $commentS * Doc comment cannot have empty line on the beginning of the comment, at the end of the comment, * and there is allowed only one empty line between two comment sections. * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $commentStart * @param int $commentEnd * @return void */ - private function checkBlankLinesInComment(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) + private function checkBlankLinesInComment(File $phpcsFile, $commentStart, $commentEnd) { $tokens = $phpcsFile->getTokens(); @@ -436,7 +436,7 @@ private function checkBlankLinesInComment(PHP_CodeSniffer_File $phpcsFile, $comm $i = 0; while ($token = $phpcsFile->findNext(T_DOC_COMMENT_STAR, $from + 1, $next - 2)) { if ($i++ > 0) { - $fix = $phpcsFile->addFixableError($error, $token); + $fix = $phpcsFile->addFixableError($error, $token, ''); if ($fix) { $firstOnLine = $phpcsFile->findFirstOnLine($empty, $token); @@ -457,12 +457,12 @@ private function checkBlankLinesInComment(PHP_CodeSniffer_File $phpcsFile, $comm /** * Checks indents of the comment (opening tag, lines with star, closing tag). * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $commentStart * @param int $commentEnd * @return void */ - private function checkCommentIndents(PHP_CodeSniffer_File $phpcsFile, $commentStart, $commentEnd) + private function checkCommentIndents(File $phpcsFile, $commentStart, $commentEnd) { $tokens = $phpcsFile->getTokens(); @@ -506,7 +506,7 @@ private function checkCommentIndents(PHP_CodeSniffer_File $phpcsFile, $commentSt $indent, strlen($spaces['content']), ]; - $fix = $phpcsFile->addFixableError($error, $commentStart, null, $data); + $fix = $phpcsFile->addFixableError($error, $commentStart, '', $data); if ($fix) { $phpcsFile->fixer->replaceToken($commentStart - 1, str_repeat(' ', $indent)); @@ -520,7 +520,7 @@ private function checkCommentIndents(PHP_CodeSniffer_File $phpcsFile, $commentSt $indent, 0, ]; - $fix = $phpcsFile->addFixableError($error, $commentStart, null, $data); + $fix = $phpcsFile->addFixableError($error, $commentStart, '', $data); if ($fix) { $phpcsFile->fixer->replaceToken( @@ -549,7 +549,7 @@ private function checkCommentIndents(PHP_CodeSniffer_File $phpcsFile, $commentSt $indent + 1, 0, ]; - $fix = $phpcsFile->addFixableError($error, $next, null, $data); + $fix = $phpcsFile->addFixableError($error, $next, '', $data); if ($fix) { $phpcsFile->fixer->replaceToken($next - 1, $phpcsFile->eolChar . ' '); @@ -562,7 +562,7 @@ private function checkCommentIndents(PHP_CodeSniffer_File $phpcsFile, $commentSt $indent + 1, strlen($spaces['content']), ]; - $fix = $phpcsFile->addFixableError($error, $next, null, $data); + $fix = $phpcsFile->addFixableError($error, $next, '', $data); if ($fix) { $phpcsFile->fixer->replaceToken($next - 1, str_repeat(' ', $indent + 1)); diff --git a/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php similarity index 97% rename from ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php rename to src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index c9fddea7..171b7f14 100644 --- a/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -8,9 +8,9 @@ namespace ZendCodingStandard\Sniffs\Commenting; -use PEAR_Sniffs_Commenting_FunctionCommentSniff; -use PHP_CodeSniffer; -use PHP_CodeSniffer_File; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FunctionCommentSniff as PEARFunctionCommentSniff; use ZendCodingStandard\CodingStandard; /** @@ -25,7 +25,7 @@ * @version Release: @package_version@ * @link http://pear.php.net/package/PHP_CodeSniffer */ -class FunctionCommentSniff extends PEAR_Sniffs_Commenting_FunctionCommentSniff +class FunctionCommentSniff extends PEARFunctionCommentSniff { /** * The current PHP version. @@ -37,14 +37,14 @@ class FunctionCommentSniff extends PEAR_Sniffs_Commenting_FunctionCommentSniff /** * Process the return comment of this function comment. * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * @param int $commentStart The position in the stack where the comment started. * * @return void */ - protected function processReturn(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart) + protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) { $tokens = $phpcsFile->getTokens(); @@ -166,14 +166,14 @@ protected function processReturn(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co /** * Process any throw tags that this function comment has. * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * @param int $commentStart The position in the stack where the comment started. * * @return void */ - protected function processThrows(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart) + protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) { $tokens = $phpcsFile->getTokens(); @@ -233,17 +233,17 @@ protected function processThrows(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co /** * Process the function parameter comments. * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * @param int $commentStart The position in the stack where the comment started. * * @return void */ - protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart) + protected function processParams(File $phpcsFile, $stackPtr, $commentStart) { if (! $this->phpVersion) { - $this->phpVersion = PHP_CodeSniffer::getConfigData('php_version'); + $this->phpVersion = Config::getConfigData('php_version'); if (! $this->phpVersion) { $this->phpVersion = PHP_VERSION_ID; } diff --git a/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php similarity index 88% rename from ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php rename to src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php index 16b68cdc..58947341 100644 --- a/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php @@ -7,8 +7,8 @@ namespace ZendCodingStandard\Sniffs\Commenting; -use PHP_CodeSniffer_File; -use PHP_CodeSniffer_Standards_AbstractVariableSniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; use ZendCodingStandard\CodingStandard; /** @@ -23,18 +23,18 @@ * @version Release: @package_version@ * @link http://pear.php.net/package/PHP_CodeSniffer */ -class VariableCommentSniff extends PHP_CodeSniffer_Standards_AbstractVariableSniff +class VariableCommentSniff extends AbstractVariableSniff { /** * Called to process class member vars. * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param 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 processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + public function processMemberVar(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $ignore = [ @@ -133,13 +133,13 @@ public function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr) * * Not required for this sniff. * - * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param File $phpcsFile The PHP_CodeSniffer file where this token was found. * @param int $stackPtr The position where the double quoted * string was found. * * @return void */ - protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + protected function processVariable(File $phpcsFile, $stackPtr) { } @@ -148,13 +148,13 @@ protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr) * * Not required for this sniff. * - * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param File $phpcsFile The PHP_CodeSniffer file where this token was found. * @param int $stackPtr The position where the double quoted * string was found. * * @return void */ - protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + protected function processVariableInString(File $phpcsFile, $stackPtr) { } } diff --git a/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php similarity index 80% rename from ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php rename to src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php index f2ed5728..56a17e40 100644 --- a/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php @@ -1,10 +1,10 @@ getTokens(); if ($tokens[$stackPtr - 1]['code'] === T_WHITESPACE) { $error = 'A double colon must not be preceded by a whitespace.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr); + $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); if ($fix) { $phpcsFile->fixer->replaceToken($stackPtr - 1, ''); @@ -34,7 +34,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) if ($tokens[$stackPtr + 1]['code'] === T_WHITESPACE) { $error = 'A double colon must not be followed by a whitespace.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr); + $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); if ($fix) { $phpcsFile->fixer->replaceToken($stackPtr + 1, ''); diff --git a/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php similarity index 79% rename from ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php rename to src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php index e23642a2..9ec84744 100644 --- a/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php @@ -1,10 +1,10 @@ getTokens(); if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) { $error = 'A "new" keyword must be followed by a single space.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr); + $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); if ($fix) { $phpcsFile->fixer->addContent($stackPtr, ' '); } } elseif ($tokens[$stackPtr + 1]['content'] !== ' ') { $error = 'A "new" keyword must be followed by a single space.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr); + $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); if ($fix) { $phpcsFile->fixer->replaceToken($stackPtr + 1, ' '); diff --git a/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php similarity index 72% rename from ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php rename to src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php index f71219c0..a2c88bd4 100644 --- a/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php @@ -1,10 +1,10 @@ getTokens(); diff --git a/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php similarity index 71% rename from ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php rename to src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php index be5ae099..0e51e76d 100644 --- a/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php +++ b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php @@ -4,10 +4,10 @@ */ namespace ZendCodingStandard\Sniffs\Methods; -use PHP_CodeSniffer_File; -use PHP_CodeSniffer_Standards_AbstractScopeSniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; -class LineAfterSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff +class LineAfterSniff extends AbstractScopeSniff { public function __construct() { @@ -15,12 +15,12 @@ public function __construct() } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr * @param int $currScope * @return void */ - protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) { $tokens = $phpcsFile->getTokens(); @@ -53,4 +53,17 @@ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $sta } } } + + /** + * Processes a token that is found outside the scope that this test is + * listening to. + * + * @param File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + } } diff --git a/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php similarity index 88% rename from ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php rename to src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php index 9a3068fc..70e7255e 100644 --- a/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -1,11 +1,11 @@ getUseStatements($phpcsFile, $stackPtr); @@ -51,11 +51,11 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $scopePtr * @return array[] */ - private function getUseStatements(PHP_CodeSniffer_File $phpcsFile, $scopePtr) + private function getUseStatements(File $phpcsFile, $scopePtr) { $tokens = $phpcsFile->getTokens(); @@ -129,11 +129,11 @@ private function compareUseStatements(array $a, array $b) } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param array[] $uses * @return void */ - private function fixAlphabeticalOrder(PHP_CodeSniffer_File $phpcsFile, array $uses) + private function fixAlphabeticalOrder(File $phpcsFile, array $uses) { $first = reset($uses); $last = end($uses); diff --git a/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php similarity index 85% rename from ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php rename to src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php index cdc9e1d8..72c68424 100644 --- a/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php @@ -1,12 +1,12 @@ getTokens(); $classPtr = $phpcsFile->findNext( - PHP_CodeSniffer_Tokens::$emptyTokens, + Tokens::$emptyTokens, $stackPtr + 1, null, true diff --git a/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php similarity index 94% rename from ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php rename to src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index 4384c236..2eab8285 100644 --- a/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -10,9 +10,9 @@ */ namespace ZendCodingStandard\Sniffs\Namespaces; -use PHP_CodeSniffer_File; -use PHP_CodeSniffer_Sniff; -use PHP_CodeSniffer_Tokens; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; use ZendCodingStandard\CodingStandard; /** @@ -23,7 +23,7 @@ * @author Jesse Donat * @copyright 2016 Capstone Digital */ -class UnusedUseStatementSniff implements PHP_CodeSniffer_Sniff +class UnusedUseStatementSniff implements Sniff { /** * @return int[] @@ -34,11 +34,11 @@ public function register() } /** - * @param PHP_CodeSniffer_File $phpcsFile The + * @param File $phpcsFile The * @param int $stackPtr * @return void */ - public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + public function process(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); @@ -55,7 +55,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } $classPtr = $phpcsFile->findPrevious( - PHP_CodeSniffer_Tokens::$emptyTokens, + Tokens::$emptyTokens, $semiColon - 1, null, true @@ -113,7 +113,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } } - $emptyTokens = PHP_CodeSniffer_Tokens::$emptyTokens; + $emptyTokens = Tokens::$emptyTokens; unset($emptyTokens[T_DOC_COMMENT_TAG]); while ($classUsed !== false) { diff --git a/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php similarity index 79% rename from ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php rename to src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php index 3d0cc60f..009f4c3a 100644 --- a/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php @@ -1,12 +1,12 @@ getTokens(); $classPtr = $phpcsFile->findNext( - PHP_CodeSniffer_Tokens::$emptyTokens, + Tokens::$emptyTokens, $stackPtr + 1, null, true @@ -38,7 +38,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $lowerContent = strtolower($tokens[$classPtr]['content']); if ($lowerContent === 'function' || $lowerContent === 'const') { $classPtr = $phpcsFile->findNext( - PHP_CodeSniffer_Tokens::$emptyTokens, + Tokens::$emptyTokens, $classPtr + 1, null, true @@ -50,7 +50,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) && $tokens[$classPtr]['content'] === '\\') ) { $error = 'Use statement cannot start with a backslash'; - $fix = $phpcsFile->addFixableError($error, $classPtr); + $fix = $phpcsFile->addFixableError($error, $classPtr, ''); if ($fix) { if ($tokens[$classPtr - 1]['code'] !== T_WHITESPACE) { diff --git a/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php similarity index 70% rename from ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php rename to src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php index 53bbb0e4..bb77f303 100644 --- a/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php +++ b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -6,11 +6,11 @@ namespace ZendCodingStandard\Sniffs\NamingConventions; -use PHP_CodeSniffer; -use PHP_CodeSniffer_File; -use PHP_CodeSniffer_Standards_AbstractVariableSniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Common; -class ValidVariableNameSniff extends PHP_CodeSniffer_Standards_AbstractVariableSniff +class ValidVariableNameSniff extends AbstractVariableSniff { const CODE_CAMEL_CAPS = 'NotCamelCaps'; @@ -28,10 +28,10 @@ class ValidVariableNameSniff extends PHP_CodeSniffer_Standards_AbstractVariableS ]; /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr Position of the double quoted string. */ - protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + protected function processVariable(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $varName = ltrim($tokens[$stackPtr]['content'], '$'); @@ -46,7 +46,7 @@ protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr) return; // skip MyClass::$variable, there might be no control over the declaration } - if (! PHP_CodeSniffer::isCamelCaps($varName, false, true, false)) { + if (! Common::isCamelCaps($varName, false, true, false)) { $error = 'Variable "%s" is not in valid camel caps format'; $data = [$varName]; $phpcsFile->addError($error, $stackPtr, self::CODE_CAMEL_CAPS, $data); @@ -54,19 +54,19 @@ protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr Position of the double quoted string. */ - protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + protected function processMemberVar(File $phpcsFile, $stackPtr) { // handled by PSR2.Classes.PropertyDeclaration } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr Position of the double quoted string. */ - protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + protected function processVariableInString(File $phpcsFile, $stackPtr) { // handled by Squiz.Strings.DoubleQuoteUsage } diff --git a/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php b/src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php similarity index 76% rename from ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php rename to src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php index d6abdd81..6b209998 100644 --- a/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php +++ b/src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php @@ -1,11 +1,11 @@ getTokens(); $prev = $phpcsFile->findPrevious( - PHP_CodeSniffer_Tokens::$emptyTokens, + Tokens::$emptyTokens, $stackPtr - 1, null, true ); $next = $phpcsFile->findNext( - PHP_CodeSniffer_Tokens::$emptyTokens, + Tokens::$emptyTokens, $stackPtr + 1, null, true @@ -40,7 +40,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line'] && $tokens[$next]['line'] !== $tokens[$stackPtr]['line'] ) { - $fix = $phpcsFile->addFixableError('Logical operator cannot be at the end of the line.', $stackPtr); + $fix = $phpcsFile->addFixableError('Logical operator cannot be at the end of the line.', $stackPtr, ''); if ($fix) { $phpcsFile->fixer->beginChangeset(); diff --git a/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php similarity index 88% rename from ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php rename to src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index e684dc5e..08cb0c03 100644 --- a/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -1,8 +1,8 @@ getTokens(); @@ -67,11 +67,11 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) /** * Checks statement before double colon - "ClassName::". * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr * @return void */ - private function checkDoubleColon(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + private function checkDoubleColon(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); @@ -99,11 +99,11 @@ private function checkDoubleColon(PHP_CodeSniffer_File $phpcsFile, $stackPtr) /** * Checks "new ClassName" statements. * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr * @return void */ - private function checkNew(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + private function checkNew(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); @@ -132,11 +132,11 @@ private function checkNew(PHP_CodeSniffer_File $phpcsFile, $stackPtr) /** * Checks "use" statements - global and traits. * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr * @return void */ - private function checkUse(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + private function checkUse(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); @@ -168,11 +168,11 @@ private function checkUse(PHP_CodeSniffer_File $phpcsFile, $stackPtr) /** * Checks "extends" and "implements" classes/interfaces. * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr * @return void */ - private function checkExtendsAndImplements(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + private function checkExtendsAndImplements(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); @@ -200,13 +200,13 @@ private function checkExtendsAndImplements(PHP_CodeSniffer_File $phpcsFile, $sta /** * Checks if class is used correctly. * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $start * @param int $end * @param bool $isGlobalUse * @return void */ - private function checkClass(PHP_CodeSniffer_File $phpcsFile, $start, $end, $isGlobalUse = false) + private function checkClass(File $phpcsFile, $start, $end, $isGlobalUse = false) { $class = trim($phpcsFile->getTokensAsString($start, $end - $start)); if ($class[0] === '\\') { @@ -248,14 +248,14 @@ private function checkClass(PHP_CodeSniffer_File $phpcsFile, $start, $end, $isGl /** * Reports new fixable error. * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $start * @param int $end * @param string $expected * @param string $actual * @return void */ - private function error(PHP_CodeSniffer_File $phpcsFile, $start, $end, $expected, $actual) + private function error(File $phpcsFile, $start, $end, $expected, $actual) { $error = 'Invalid class name case: expected %s; found %s'; $data = [ @@ -277,10 +277,10 @@ private function error(PHP_CodeSniffer_File $phpcsFile, $start, $end, $expected, /** * Returns array of imported classes. Key is lowercase name, and value is FQCN. * - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @return array */ - private function getGlobalUses(PHP_CodeSniffer_File $phpcsFile) + private function getGlobalUses(File $phpcsFile) { $tokens = $phpcsFile->getTokens(); @@ -345,11 +345,11 @@ private function hasDifferentCase($class) } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr * @return string */ - private function getNamespace(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + private function getNamespace(File $phpcsFile, $stackPtr) { if ($nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr - 1)) { $nsEnd = $phpcsFile->findNext([T_NS_SEPARATOR, T_STRING, T_WHITESPACE], $nsStart + 1, null, true); diff --git a/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php similarity index 72% rename from ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php rename to src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php index e9fd23d4..39468d1e 100644 --- a/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php @@ -1,11 +1,11 @@ getTokens(); $end = $phpcsFile->findNext( - array_merge(PHP_CodeSniffer_Tokens::$emptyTokens, [ + array_merge(Tokens::$emptyTokens, [ T_ANON_CLASS, T_NS_SEPARATOR, T_SELF, @@ -40,14 +40,14 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) if ($tokens[$end]['code'] !== T_OPEN_PARENTHESIS) { $last = $phpcsFile->findPrevious( - PHP_CodeSniffer_Tokens::$emptyTokens, + Tokens::$emptyTokens, $end - 1, $stackPtr + 1, true ); $error = 'Missing parenthesis on instantiating a new class.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr); + $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); if ($fix) { $phpcsFile->fixer->addContent($last, '()'); diff --git a/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php b/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php similarity index 63% rename from ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php rename to src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php index 9389cac5..48457c26 100644 --- a/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php @@ -1,9 +1,9 @@ getTokens(); @@ -34,7 +34,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } $nextNonEmpty = $phpcsFile->findNext( - PHP_CodeSniffer_Tokens::$emptyTokens, + Tokens::$emptyTokens, $stackPtr + 1, null, true diff --git a/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php similarity index 90% rename from ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php rename to src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php index a1f2faf6..56315d4f 100644 --- a/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -10,9 +10,9 @@ namespace ZendCodingStandard\Sniffs\PHP; -use PHP_CodeSniffer_File; -use PHP_CodeSniffer_Sniff; -use PHP_CodeSniffer_Tokens; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; /** * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) @@ -30,7 +30,7 @@ * - bool instead of boolean * - int instead of integer */ -class TypeCastingSniff implements PHP_CodeSniffer_Sniff +class TypeCastingSniff implements Sniff { /** * Returns an array of tokens this test wants to listen for. @@ -44,18 +44,18 @@ class TypeCastingSniff implements PHP_CodeSniffer_Sniff */ public function register() { - return array_merge(PHP_CodeSniffer_Tokens::$castTokens, [T_BOOLEAN_NOT]); + return array_merge(Tokens::$castTokens, [T_BOOLEAN_NOT]); } /** * Processes this test, when one of its tokens is encountered. * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param 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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + public function process(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); diff --git a/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php b/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php similarity index 77% rename from ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php rename to src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php index 46de0c2c..5c2c8556 100644 --- a/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php +++ b/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php @@ -1,17 +1,17 @@ getTokens(); @@ -22,7 +22,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } $error = 'String concatenation character is not allowed at the end of the line.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr); + $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); if ($fix) { $phpcsFile->fixer->beginChangeset(); diff --git a/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php similarity index 73% rename from ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php rename to src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php index 38cb8e61..1a056294 100644 --- a/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php @@ -1,10 +1,10 @@ getTokens(); $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($next && $tokens[$stackPtr]['line'] < $tokens[$next]['line'] - 2) { - $fix = $phpcsFile->addFixableError('Unexpected blank line found.', $stackPtr + 1); + $fix = $phpcsFile->addFixableError('Unexpected blank line found.', $stackPtr + 1, ''); if ($fix) { $phpcsFile->fixer->replaceToken($stackPtr + 1, ''); diff --git a/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php similarity index 88% rename from ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php rename to src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index 29964902..36b7e591 100644 --- a/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -14,11 +14,11 @@ */ namespace ZendCodingStandard\Sniffs\WhiteSpace; -use PHP_CodeSniffer_File; -use PHP_CodeSniffer_Sniff; -use PHP_CodeSniffer_Tokens; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; -class CommaSpacingSniff implements PHP_CodeSniffer_Sniff +class CommaSpacingSniff implements Sniff { /** * @return int[] @@ -29,11 +29,11 @@ public function register() } /** - * @param PHP_CodeSniffer_File $phpcsFile + * @param File $phpcsFile * @param int $stackPtr * @return void */ - public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + public function process(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); @@ -69,14 +69,14 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) // Check if this is multidimensional array. $openArray = $phpcsFile->findPrevious([T_OPEN_SHORT_ARRAY], $stackPtr); $beforeOpening = $phpcsFile->findPrevious( - PHP_CodeSniffer_Tokens::$emptyTokens, + Tokens::$emptyTokens, $openArray - 1, null, true ); $closeArray = $phpcsFile->findNext([T_CLOSE_SHORT_ARRAY], $stackPtr); $afterClosing = $phpcsFile->findNext( - array_merge(PHP_CodeSniffer_Tokens::$emptyTokens, [T_COMMA]), + array_merge(Tokens::$emptyTokens, [T_COMMA]), $closeArray + 1, null, true diff --git a/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php similarity index 84% rename from ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php rename to src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php index e052baa8..9422a156 100644 --- a/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php @@ -1,10 +1,10 @@ getTokens(); $token = $tokens[$stackPtr]; @@ -40,7 +40,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) if ($tokens[$firstContent]['line'] > $tokens[$scopeOpener]['line'] + 1) { $error = sprintf('Blank line found at start of %s', $token['content']); - $fix = $phpcsFile->addFixableError($error, $scopeOpener + 1); + $fix = $phpcsFile->addFixableError($error, $scopeOpener + 1, ''); if ($fix) { $phpcsFile->fixer->beginChangeset(); diff --git a/ZendCodingStandard/ruleset.xml b/src/ZendCodingStandard/ruleset.xml similarity index 100% rename from ZendCodingStandard/ruleset.xml rename to src/ZendCodingStandard/ruleset.xml diff --git a/test/Ruleset.php b/test/Ruleset.php new file mode 100644 index 00000000..3a7f983f --- /dev/null +++ b/test/Ruleset.php @@ -0,0 +1,16 @@ + $bool) { + $newClassName = str_replace('php_codesniffer\\standards\\', '', $className); + unset($restrictions[$className]); + $restrictions[$newClassName] = $bool; + } + + parent::registerSniffs($files, $restrictions, $exclusions); // TODO: Change the autogenerated stub + } +} diff --git a/ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc b/test/Sniffs/Arrays/FormatUnitTest.inc similarity index 100% rename from ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc rename to test/Sniffs/Arrays/FormatUnitTest.inc diff --git a/ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc.fixed b/test/Sniffs/Arrays/FormatUnitTest.inc.fixed similarity index 100% rename from ZendCodingStandard/Tests/Arrays/FormatUnitTest.inc.fixed rename to test/Sniffs/Arrays/FormatUnitTest.inc.fixed diff --git a/ZendCodingStandard/Tests/Arrays/FormatUnitTest.php b/test/Sniffs/Arrays/FormatUnitTest.php similarity index 90% rename from ZendCodingStandard/Tests/Arrays/FormatUnitTest.php rename to test/Sniffs/Arrays/FormatUnitTest.php index 0ca58686..1425984f 100644 --- a/ZendCodingStandard/Tests/Arrays/FormatUnitTest.php +++ b/test/Sniffs/Arrays/FormatUnitTest.php @@ -1,7 +1,7 @@ phpcs = new PHP_CodeSniffer(); + // Initialize tokens constants + new Tokens(); } + /** + * Get a list of all test files to check. + * + * These will have the same base as the sniff name but different extensions. + * We ignore the .php file as it is the class. + * + * @param string $testFileBase The base path that the unit tests files will have. + * @return string[] + */ protected function getTestFiles($testFileBase) { $testFiles = []; $dir = substr($testFileBase, 0, strrpos($testFileBase, DIRECTORY_SEPARATOR)); - $di = new \DirectoryIterator($dir); + $di = new DirectoryIterator($dir); foreach ($di as $file) { - if (! $file->isFile()) { - continue; - } - $path = $file->getPathname(); - if (substr($path, 0, strlen($testFileBase)) === $testFileBase - && $path !== $testFileBase . 'php' - && substr($path, -5) !== 'fixed' - ) { - $testFiles[] = $path; + if (strpos($path, $testFileBase) === 0) { + if ($path !== $testFileBase . 'php' + && substr($path, -5) !== 'fixed' + ) { + $testFiles[] = $path; + } } } + // Put them in order. sort($testFiles); return $testFiles; } - final public function testSniff() + /** + * Should this test be skipped for some reason. + * + * @return bool + */ + protected function shouldSkipTest() { - $basename = substr(get_class($this), 0, -8); + return false; + } - $standardName = substr($basename, 0, strpos($basename, '\\')); + /** + * Tests the extending classes Sniff class. + * + * @return void + */ + final public function testSniff() + { + // Skip this test if we can't run in this environment. + if ($this->shouldSkipTest()) { + $this->markTestSkipped(); + } - $parts = explode('\\', $basename); - $sniffCode = $parts[0] . '.' . $parts[2] . '.' . $parts[3]; + $sniffCode = Common::getSniffCode(get_class($this)); + $sniffCode = str_replace('Test.', '.', $sniffCode); + list($standardName, $categoryName, $sniffName) = explode('.', $sniffCode); - $testFileBase = __DIR__ - . '/../../' - . str_replace('\\', DIRECTORY_SEPARATOR, $basename) . 'UnitTest.'; + $testFileBase = $this->testsDir . $categoryName . DIRECTORY_SEPARATOR . $sniffName . 'UnitTest.'; + // Get a list of all test files to check. $testFiles = $this->getTestFiles($testFileBase); - $this->phpcs->initStandard($standardName, [$sniffCode]); - $this->phpcs->setIgnorePatterns([]); + $config = new Config(); + $config->cache = false; + $config->standards = [$standardName]; + $config->sniffs = [$sniffCode]; + $config->ignored = []; + + $ruleset = new Ruleset($config); $failureMessages = []; foreach ($testFiles as $testFile) { $filename = basename($testFile); + $oldConfig = $config->getSettings(); try { - $phpcsFile = $this->phpcs->processFile($testFile); - } catch (\Exception $e) { - $this->fail(sprintf( - 'An unexpected exception has been caught: %s', - $e->getMessage() - )); + $this->setCliValues($filename, $config); + $phpcsFile = new LocalFile($testFile, $ruleset, $config); + $phpcsFile->process(); + } catch (RuntimeException $e) { + $this->fail(sprintf('An unexpected exception has been caught: %s', $e->getMessage())); } $failures = $this->generateFailureMessages($phpcsFile); @@ -90,12 +123,8 @@ final public function testSniff() // Attempt to fix the errors. $phpcsFile->fixer->fixFile(); $fixable = $phpcsFile->getFixableCount(); - if ($fixable) { - $failureMessages[] = sprintf( - 'Failed to fix %d fixable violations in %s', - $fixable, - $filename - ); + if ($fixable > 0) { + $failureMessages[] = sprintf('Failed to fix %d fixable violations in %s', $fixable, $filename); } // Check for a .fixed file to check for accuracy of fixes. @@ -106,22 +135,33 @@ final public function testSniff() $filename = basename($testFile); $fixedFilename = basename($fixedFile); $failureMessages[] = sprintf( - 'Fixed version of %s does not match expected version in %s; the diff is' . PHP_EOL . '%s', + 'Fixed version of %s does not match expected version in %s; the diff is%s%s', $filename, $fixedFilename, + PHP_EOL, $diff ); } } } + + // Restore the config. + $config->setSettings($oldConfig); } - if (! empty($failureMessages)) { + if ($failureMessages) { $this->fail(implode(PHP_EOL, $failureMessages)); } } - public function generateFailureMessages(PHP_CodeSniffer_File $file) + /** + * Generate a list of test failures for a given sniffed file. + * + * @param LocalFile $file The file being tested. + * @return array + * @throws RuntimeException + */ + public function generateFailureMessages(LocalFile $file) { $testFile = $file->getFilename(); @@ -131,11 +171,11 @@ public function generateFailureMessages(PHP_CodeSniffer_File $file) $expectedWarnings = $this->getWarningList(basename($testFile)); if (! is_array($expectedErrors)) { - throw new PHP_CodeSniffer_Exception('getErrorList() must return an array'); + throw new RuntimeException('getErrorList() must return an array'); } if (! is_array($expectedWarnings)) { - throw new PHP_CodeSniffer_Exception('getWarningList() must return an array'); + throw new RuntimeException('getWarningList() must return an array'); } // We merge errors and warnings together to make it easier @@ -150,10 +190,10 @@ public function generateFailureMessages(PHP_CodeSniffer_File $file) foreach ($lineErrors as $column => $errors) { if (! isset($allProblems[$line])) { $allProblems[$line] = [ - 'expected_errors' => 0, + 'expected_errors' => 0, 'expected_warnings' => 0, - 'found_errors' => [], - 'found_warnings' => [], + 'found_errors' => [], + 'found_warnings' => [], ]; } @@ -165,17 +205,6 @@ public function generateFailureMessages(PHP_CodeSniffer_File $file) $errorsTemp = []; foreach ($errors as $foundError) { $errorsTemp[] = $foundError['message'] . ' (' . $foundError['source'] . ')'; - - $source = $foundError['source']; - if (! in_array($source, $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'])) { - $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'][] = $source; - } - - if ($foundError['fixable'] === true - && ! in_array($source, $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES']) - ) { - $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'][] = $source; - } } $allProblems[$line]['found_errors'] = array_merge($foundErrorsTemp, $errorsTemp); @@ -193,10 +222,10 @@ public function generateFailureMessages(PHP_CodeSniffer_File $file) foreach ($expectedErrors as $line => $numErrors) { if (! isset($allProblems[$line])) { $allProblems[$line] = [ - 'expected_errors' => 0, + 'expected_errors' => 0, 'expected_warnings' => 0, - 'found_errors' => [], - 'found_warnings' => [], + 'found_errors' => [], + 'found_warnings' => [], ]; } @@ -207,10 +236,10 @@ public function generateFailureMessages(PHP_CodeSniffer_File $file) foreach ($lineWarnings as $column => $warnings) { if (! isset($allProblems[$line])) { $allProblems[$line] = [ - 'expected_errors' => 0, + 'expected_errors' => 0, 'expected_warnings' => 0, - 'found_errors' => [], - 'found_warnings' => [], + 'found_errors' => [], + 'found_warnings' => [], ]; } @@ -239,10 +268,10 @@ public function generateFailureMessages(PHP_CodeSniffer_File $file) foreach ($expectedWarnings as $line => $numWarnings) { if (! isset($allProblems[$line])) { $allProblems[$line] = [ - 'expected_errors' => 0, + 'expected_errors' => 0, 'expected_warnings' => 0, - 'found_errors' => [], - 'found_warnings' => [], + 'found_errors' => [], + 'found_warnings' => [], ]; } @@ -262,13 +291,13 @@ public function generateFailureMessages(PHP_CodeSniffer_File $file) $foundString = ''; if ($expectedErrors !== $numErrors || $expectedWarnings !== $numWarnings) { - $lineMessage = sprintf('[LINE %s]', $line); + $lineMessage = '[LINE ' . $line . ']'; $expectedMessage = 'Expected '; - $foundMessage = sprintf('in %s but found ', basename($testFile)); + $foundMessage = 'in ' . basename($testFile) . ' but found '; if ($expectedErrors !== $numErrors) { - $expectedMessage .= sprintf('%s error(s)', $expectedErrors); - $foundMessage .= sprintf('%s error(s)', $numErrors); + $expectedMessage .= $expectedErrors . ' error(s)'; + $foundMessage .= $numErrors . ' error(s)'; if ($numErrors !== 0) { $foundString .= 'error(s)'; $errors .= implode(PHP_EOL . ' -> ', $problems['found_errors']); @@ -286,11 +315,11 @@ public function generateFailureMessages(PHP_CodeSniffer_File $file) } if ($expectedWarnings !== $numWarnings) { - $expectedMessage .= sprintf('%s warning(s)', $expectedWarnings); - $foundMessage .= sprintf('%s warning(s)', $numWarnings); + $expectedMessage .= $expectedWarnings . ' warning(s)'; + $foundMessage .= $numWarnings . ' warning(s)'; if ($numWarnings !== 0) { $foundString .= 'warning(s)'; - if (! empty($errors)) { + if ($errors) { $errors .= PHP_EOL . ' -> '; } @@ -300,7 +329,7 @@ public function generateFailureMessages(PHP_CodeSniffer_File $file) $fullMessage = sprintf('%s %s %s.', $lineMessage, $expectedMessage, $foundMessage); if ($errors !== '') { - $fullMessage .= sprintf(' The %s found were:' . PHP_EOL . ' -> %s', $foundString, $errors); + $fullMessage .= sprintf(' The %s found were:%s -> %s', $foundString, PHP_EOL, $errors); } $failureMessages[] = $fullMessage; @@ -310,6 +339,18 @@ public function generateFailureMessages(PHP_CodeSniffer_File $file) return $failureMessages; } + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $filename The name of the file being tested. + * @param Config $config The config data for the run. + * @return array + */ + public function setCliValues($filename, Config $config) + { + return []; + } + /** * Returns the lines where errors should occur. * diff --git a/ZendCodingStandard/Tests/WhiteSpace/BlankLineUnitTest.inc b/test/Sniffs/WhiteSpace/BlankLineUnitTest.inc similarity index 100% rename from ZendCodingStandard/Tests/WhiteSpace/BlankLineUnitTest.inc rename to test/Sniffs/WhiteSpace/BlankLineUnitTest.inc diff --git a/ZendCodingStandard/Tests/WhiteSpace/BlankLineUnitTest.inc.fixed b/test/Sniffs/WhiteSpace/BlankLineUnitTest.inc.fixed similarity index 100% rename from ZendCodingStandard/Tests/WhiteSpace/BlankLineUnitTest.inc.fixed rename to test/Sniffs/WhiteSpace/BlankLineUnitTest.inc.fixed diff --git a/ZendCodingStandard/Tests/WhiteSpace/BlankLineUnitTest.php b/test/Sniffs/WhiteSpace/BlankLineUnitTest.php similarity index 78% rename from ZendCodingStandard/Tests/WhiteSpace/BlankLineUnitTest.php rename to test/Sniffs/WhiteSpace/BlankLineUnitTest.php index 2c116dc0..7a34b27c 100644 --- a/ZendCodingStandard/Tests/WhiteSpace/BlankLineUnitTest.php +++ b/test/Sniffs/WhiteSpace/BlankLineUnitTest.php @@ -1,7 +1,7 @@ Date: Tue, 30 May 2017 19:00:57 +0200 Subject: [PATCH 048/225] Optimize conditions - changed `substr` to `strpos` --- src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index 1c6a6863..9e85da16 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -148,8 +148,8 @@ private function multiLineArray(File $phpcsFile, $stackPtr) } if ($tokens[$next]['code'] === T_COMMENT - && (substr($tokens[$next]['content'], 0, 2) === '//' - || substr($tokens[$next]['content'], 0, 1) === '#') + && (strpos($tokens[$next]['content'], '//') === 0 + || strpos($tokens[$next]['content'], '#') === 0) ) { $end = $next; } else { From 93994eab7a8ff62cc591875dce50847702246213 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 30 May 2017 19:02:03 +0200 Subject: [PATCH 049/225] Remove redundant brackets --- .../Sniffs/Commenting/FunctionCommentSniff.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 171b7f14..8ecb8a2e 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -384,7 +384,7 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) $content .= $param['commentLines'][0]['comment']; } - $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + $phpcsFile->fixer->replaceToken($param['tag'] + 2, $content); } } elseif (count($typeNames) === 1) { // Check type hint for array and custom type. @@ -475,7 +475,7 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) $content .= $param['var']; $content .= str_repeat(' ', $param['var_space']); $content .= $param['commentLines'][0]['comment']; - $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + $phpcsFile->fixer->replaceToken($param['tag'] + 2, $content); // Fix up the indent of additional comment lines. foreach ($param['commentLines'] as $lineNum => $line) { @@ -487,7 +487,7 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) $newIndent = ($param['commentLines'][$lineNum]['indent'] + $spaces - $param['type_space']); $phpcsFile->fixer->replaceToken( - ($param['commentLines'][$lineNum]['token'] - 1), + $param['commentLines'][$lineNum]['token'] - 1, str_repeat(' ', $newIndent) ); } @@ -544,7 +544,7 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) $content .= $param['var']; $content .= str_repeat(' ', $spaces); $content .= $param['commentLines'][0]['comment']; - $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + $phpcsFile->fixer->replaceToken($param['tag'] + 2, $content); // Fix up the indent of additional comment lines. foreach ($param['commentLines'] as $lineNum => $line) { @@ -556,7 +556,7 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) $newIndent = ($param['commentLines'][$lineNum]['indent'] + $spaces - $param['var_space']); $phpcsFile->fixer->replaceToken( - ($param['commentLines'][$lineNum]['token'] - 1), + $param['commentLines'][$lineNum]['token'] - 1, str_repeat(' ', $newIndent) ); } From 30a9d7f12cd0d1e0a27f1dfbcbbf6b4a4402cef1 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 31 May 2017 12:25:50 +0200 Subject: [PATCH 050/225] FunctionComment sniff checks `@inheritDoc` tags --- .../Commenting/FunctionCommentSniff.php | 104 +++++++++++++----- .../Commenting/FunctionCommentUnitTest.inc | 24 ++++ .../FunctionCommentUnitTest.inc.fixed | 24 ++++ .../Commenting/FunctionCommentUnitTest.php | 20 ++++ 4 files changed, 146 insertions(+), 26 deletions(-) create mode 100644 test/Sniffs/Commenting/FunctionCommentUnitTest.inc create mode 100644 test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed create mode 100644 test/Sniffs/Commenting/FunctionCommentUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 8ecb8a2e..8838a295 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -1,11 +1,4 @@ - * @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 - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer - */ class FunctionCommentSniff extends PEARFunctionCommentSniff { /** @@ -34,6 +15,13 @@ class FunctionCommentSniff extends PEARFunctionCommentSniff */ private $phpVersion; + /** + * If function comment contains @inheritDoc tag. + * + * @var int[] + */ + private $hasInheritDoc = []; + /** * Process the return comment of this function comment. * @@ -41,7 +29,6 @@ class FunctionCommentSniff extends PEARFunctionCommentSniff * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * @param int $commentStart The position in the stack where the comment started. - * * @return void */ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) @@ -80,7 +67,7 @@ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) $suggestedNames = []; foreach ($typeNames as $i => $typeName) { $suggestedName = CodingStandard::suggestType($typeName); - if (in_array($suggestedName, $suggestedNames) === false) { + if (! in_array($suggestedName, $suggestedNames)) { $suggestedNames[] = $suggestedName; } } @@ -131,7 +118,7 @@ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) $phpcsFile->addError($error, $return, 'InvalidReturnVoid'); } } - }//end if + } } elseif ($returnType !== 'mixed') { $returnTypes = explode('|', $returnType); @@ -157,7 +144,7 @@ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) } } } - } else { + } elseif (! $this->hasInheritDocTag($phpcsFile, $stackPtr, $commentStart)) { $error = 'Missing @return tag in function comment'; $phpcsFile->addError($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn'); } @@ -170,7 +157,6 @@ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * @param int $commentStart The position in the stack where the comment started. - * * @return void */ protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) @@ -231,13 +217,75 @@ protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) } /** - * Process the function parameter comments. + * Checks if function comment contains @inheritDoc tag. + * Methods should run only once. * * @param File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * @param int $commentStart The position in the stack where the comment started. + * @return bool + */ + protected function hasInheritDocTag(File $phpcsFile, $stackPtr, $commentStart) + { + if (isset($this->hasInheritDoc[$stackPtr])) { + return $this->hasInheritDoc[$stackPtr]; + } + + $tokens = $phpcsFile->getTokens(); + + $commentEnd = $tokens[$commentStart]['comment_closer']; + $commentContent = $phpcsFile->getTokensAsString($commentStart + 1, $commentEnd - $commentStart - 1); + + if (preg_match('/\*.*\{(@inheritDoc)\}/i', $commentContent, $m)) { + if ($m[1] !== '@inheritDoc') { + $data = ['@inheritDoc', $m[1]]; + $error = 'Expected {%s}, found {%s}.'; + $fix = $phpcsFile->addFixableError($error, $commentStart, 'InheritDocCase', $data); + + if ($fix) { + $newCommentContent = str_replace('{' . $m[1] . '}', '{@inheritDoc}', $commentContent); + $phpcsFile->fixer->beginChangeset(); + for ($i = $commentStart + 1; $i < $commentEnd; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->addContent($commentStart + 1, $newCommentContent); + $phpcsFile->fixer->endChangeset(); + } + } + + $this->hasInheritDoc[$stackPtr] = true; + return $this->hasInheritDoc[$stackPtr]; + } + + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if (strtolower($tokens[$tag]['content']) === '@inheritdoc') { + if ($tokens[$tag]['content'] !== '@inheritDoc') { + $data = ['@inheritDoc', $tokens[$tag]['content']]; + $error = 'Expected %s, found %s.'; + $fix = $phpcsFile->addFixableError($error, $tag, 'InheritDocCase', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($tag, '@inheritDoc'); + } + } + + $this->hasInheritDoc[$stackPtr] = true; + return $this->hasInheritDoc[$stackPtr]; + } + } + + $this->hasInheritDoc[$stackPtr] = false; + return $this->hasInheritDoc[$stackPtr]; + } + + /** + * Process the function parameter comments. * + * @param File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. * @return void */ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) @@ -436,7 +484,7 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) $param['var'], ]; $phpcsFile->addError($error, $stackPtr, 'IncorrectTypeHint', $data); - }//end if + } } elseif ($suggestedTypeHint === '' && isset($realParams[$pos])) { $typeHint = $realParams[$pos]['type_hint']; if ($typeHint !== '') { @@ -578,6 +626,10 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) } } + if ($this->hasInheritDocTag($phpcsFile, $stackPtr, $commentStart)) { + return; + } + $realNames = []; foreach ($realParams as $realParam) { $realNames[] = $realParam['name']; diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc new file mode 100644 index 00000000..1dbafafb --- /dev/null +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc @@ -0,0 +1,24 @@ + 1, + 16 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 93f27d4b1a98dbbf2893c01a5fda8dbb2e60904c Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 31 May 2017 14:17:42 +0200 Subject: [PATCH 051/225] Added ReturnValueWithoutBrackets sniff --- .../ReturnValueWithoutBracketsSniff.php | 58 +++++++++++++++++++ .../ReturnValueWithoutBracketsUnitTest.inc | 43 ++++++++++++++ ...turnValueWithoutBracketsUnitTest.inc.fixed | 43 ++++++++++++++ .../ReturnValueWithoutBracketsUnitTest.php | 24 ++++++++ 4 files changed, 168 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/Methods/ReturnValueWithoutBracketsSniff.php create mode 100644 test/Sniffs/Methods/ReturnValueWithoutBracketsUnitTest.inc create mode 100644 test/Sniffs/Methods/ReturnValueWithoutBracketsUnitTest.inc.fixed create mode 100644 test/Sniffs/Methods/ReturnValueWithoutBracketsUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Methods/ReturnValueWithoutBracketsSniff.php b/src/ZendCodingStandard/Sniffs/Methods/ReturnValueWithoutBracketsSniff.php new file mode 100644 index 00000000..b57deaa4 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Methods/ReturnValueWithoutBracketsSniff.php @@ -0,0 +1,58 @@ +getTokens(); + + $firstContent = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); + // If the first non-whitespace token is not an opening parenthesis, then we are not concerned. + if ($tokens[$firstContent]['code'] !== T_OPEN_PARENTHESIS) { + $phpcsFile->recordMetric($stackPtr, 'Brackets around returned value', 'no'); + return; + } + + // Find the end of the expression. + $end = $stackPtr; + do { + $end = $phpcsFile->findNext([T_SEMICOLON, T_CLOSE_TAG], $end + 1, null, false); + } while ($tokens[$end]['level'] !== $tokens[$stackPtr]['level']); + + // If the token before the semi-colon is not a closing parenthesis, then we are not concerned. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, $end - 1, null, true); + if ($tokens[$prev]['code'] !== T_CLOSE_PARENTHESIS) { + $phpcsFile->recordMetric($stackPtr, 'Brackets around returned value', 'no'); + return; + } + + // If the parenthesis don't match, then we are not concerned. + if ($tokens[$firstContent]['parenthesis_closer'] !== $prev) { + $phpcsFile->recordMetric($stackPtr, 'Brackets around returned value', 'no'); + return; + } + + $phpcsFile->recordMetric($stackPtr, 'Brackets around returned value', 'yes'); + + $error = 'Returned value should not be bracketed'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'HasBracket'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($firstContent, ''); + if ($tokens[$firstContent - 1]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->addContent($firstContent - 1, ' '); + } + $phpcsFile->fixer->replaceToken($prev, ''); + $phpcsFile->fixer->endChangeset(); + } + } +} diff --git a/test/Sniffs/Methods/ReturnValueWithoutBracketsUnitTest.inc b/test/Sniffs/Methods/ReturnValueWithoutBracketsUnitTest.inc new file mode 100644 index 00000000..dedf1d6d --- /dev/null +++ b/test/Sniffs/Methods/ReturnValueWithoutBracketsUnitTest.inc @@ -0,0 +1,43 @@ + 1, + 12 => 1, + 22 => 1, + 23 => 1, + 30 => 1, + 36 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From cbab98d99a86fb429d9cd4c74ace848ca09cc8fb Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 31 May 2017 14:18:09 +0200 Subject: [PATCH 052/225] Added default constant values in default phpunit configuration --- phpunit.xml.dist | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 1d3a2ed2..cd58953e 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -10,4 +10,9 @@ ./src + + + + + From 23c52b6e331ab886265cfc5ec25c07a3d58cf0c2 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 31 May 2017 20:49:59 +0200 Subject: [PATCH 053/225] Fix phpunit tests with PHP_CodeSniffer 3.0.0 --- composer.lock | 12 ++++++------ phpunit.xml.dist | 1 - test/Sniffs/TestCase.php | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index a940f9da..12a7f8e6 100644 --- a/composer.lock +++ b/composer.lock @@ -1269,16 +1269,16 @@ }, { "name": "symfony/yaml", - "version": "v3.2.8", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6" + "reference": "885db865f6b2b918404a1fae28f9ac640f71f994" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/acec26fcf7f3031e094e910b94b002fa53d4e4d6", - "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6", + "url": "https://api.github.com/repos/symfony/yaml/zipball/885db865f6b2b918404a1fae28f9ac640f71f994", + "reference": "885db865f6b2b918404a1fae28f9ac640f71f994", "shasum": "" }, "require": { @@ -1293,7 +1293,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-master": "3.3-dev" } }, "autoload": { @@ -1320,7 +1320,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-05-01T14:55:58+00:00" + "time": "2017-05-28T10:56:20+00:00" }, { "name": "webmozart/assert", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index cd58953e..56d8195e 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -11,7 +11,6 @@ - diff --git a/test/Sniffs/TestCase.php b/test/Sniffs/TestCase.php index 22b36bad..99648b5e 100644 --- a/test/Sniffs/TestCase.php +++ b/test/Sniffs/TestCase.php @@ -97,7 +97,7 @@ final public function testSniff() $config = new Config(); $config->cache = false; - $config->standards = [$standardName]; + $config->standards = [sprintf('src/%s', $standardName)]; $config->sniffs = [$sniffCode]; $config->ignored = []; From 402bd9d11103172b11a8ac275105047820714515 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 31 May 2017 20:57:10 +0200 Subject: [PATCH 054/225] Use property value instead of fixed string --- test/Sniffs/TestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Sniffs/TestCase.php b/test/Sniffs/TestCase.php index 99648b5e..90a45832 100644 --- a/test/Sniffs/TestCase.php +++ b/test/Sniffs/TestCase.php @@ -97,7 +97,7 @@ final public function testSniff() $config = new Config(); $config->cache = false; - $config->standards = [sprintf('src/%s', $standardName)]; + $config->standards = [sprintf('%s/%s', $this->standardsDir, $standardName)]; $config->sniffs = [$sniffCode]; $config->ignored = []; From 71158ea72aaa78b2818201e7400c63baa701d80d Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 2 Jun 2017 12:14:48 +0200 Subject: [PATCH 055/225] PHP 5.6 compatibility checks Sniffs check if code is compatible with PHP 5.6. For example simple type hinting is not suggested here. --- src/ZendCodingStandard/ruleset.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ZendCodingStandard/ruleset.xml b/src/ZendCodingStandard/ruleset.xml index df78abb8..511ec2d6 100755 --- a/src/ZendCodingStandard/ruleset.xml +++ b/src/ZendCodingStandard/ruleset.xml @@ -6,6 +6,9 @@ + + + From 6d265514c664c4edcb79a2749a4347882359f3e9 Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 2 Jun 2017 12:15:21 +0200 Subject: [PATCH 056/225] Default configuration in tests fix --- test/Sniffs/TestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Sniffs/TestCase.php b/test/Sniffs/TestCase.php index 90a45832..c900c6a7 100644 --- a/test/Sniffs/TestCase.php +++ b/test/Sniffs/TestCase.php @@ -95,7 +95,7 @@ final public function testSniff() // Get a list of all test files to check. $testFiles = $this->getTestFiles($testFileBase); - $config = new Config(); + $config = new Config([], false); $config->cache = false; $config->standards = [sprintf('%s/%s', $this->standardsDir, $standardName)]; $config->sniffs = [$sniffCode]; From 1cd328dbd603f73db7e50497b37824cf3f3be071 Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 2 Jun 2017 12:17:22 +0200 Subject: [PATCH 057/225] Added `@dataProvider` tag checks - only allowed for `test*` methods - tag should be first (first tag, description always before if present) - data provider shouldn't have Provider suffix - should be one empty line before and after tag --- .../Commenting/FunctionCommentSniff.php | 168 ++++++++++++++++++ .../Commenting/FunctionCommentUnitTest.1.inc | 71 ++++++++ .../FunctionCommentUnitTest.1.inc.fixed | 75 ++++++++ .../Commenting/FunctionCommentUnitTest.php | 16 ++ 4 files changed, 330 insertions(+) create mode 100644 test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc create mode 100644 test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc.fixed diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 8838a295..26d990d3 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -279,6 +279,173 @@ protected function hasInheritDocTag(File $phpcsFile, $stackPtr, $commentStart) return $this->hasInheritDoc[$stackPtr]; } + /** + * Process the @dataProvider tag of test's functions. + * + * @param File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * @return void + */ + protected function processDataProvider(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + $tags = $tokens[$commentStart]['comment_tags']; + + // Checks @dataProvider tags + foreach ($tags as $pos => $tag) { + if (strtolower($tokens[$tag]['content']) !== '@dataprovider') { + continue; + } + + // Check if method name starts from "test". + $functionPtr = $phpcsFile->findNext(T_FUNCTION, $tag + 1); + $namePtr = $phpcsFile->findNext(T_STRING, $functionPtr + 1); + $functionName = $tokens[$namePtr]['content']; + + if (strpos($functionName, 'test') !== 0) { + $error = 'Tag @dataProvider is allowed only for test* methods.'; + $phpcsFile->addError($error, $tag, 'DataProviderTestMethod'); + } + + // Check if data provider name is given and does not have "Provider" suffix. + if ($tokens[$tag + 1]['code'] !== T_DOC_COMMENT_WHITESPACE + || $tokens[$tag + 2]['code'] !== T_DOC_COMMENT_STRING + ) { + $error = 'Missing data provider name.'; + $phpcsFile->addError($error, $tag, 'DataProviderMissing'); + } else { + $providerName = $tokens[$tag + 2]['content']; + + if (preg_match('/Provider$/', $providerName)) { + $error = 'Data provider name should have "Provider" suffix.'; + $phpcsFile->addError($error, $tag, 'DataProviderInvalidName'); + } + } + + // Check if @dataProvider tag is first tag. + for ($i = $pos - 1; $i >= 0; --$i) { + $prevTag = $tags[$i]; + if (strtolower($tokens[$prevTag]['content']) !== '@dataprovider') { + $error = 'Tag @dataProvider must be first tag in function comment.'; + $fix = $phpcsFile->addFixableError($error, $tag, 'DataProviderNotFirstTag'); + + if ($fix) { + $first = $last = $tag; + while ($tokens[$first]['line'] === $tokens[$tag]['line']) { + --$first; + } + while ($tokens[$last]['line'] === $tokens[$tag]['line']) { + ++$last; + } + $content = $phpcsFile->getTokensAsString($first + 1, $last - $first - 1); + + $prevLine = $prevTag; + while ($tokens[$prevLine]['line'] === $tokens[$prevTag]['line']) { + --$prevLine; + } + + $phpcsFile->fixer->beginChangeset(); + for ($j = $first + 1; $j < $last; ++$j) { + $phpcsFile->fixer->replaceToken($j, ''); + } + $phpcsFile->fixer->addContent($prevLine, $content); + $phpcsFile->fixer->endChangeset(); + } + + continue 2; + } + } + + if ($tokens[$tag]['content'] !== '@dataProvider') { + $data = ['@dataProvider', $tokens[$tag]['content']]; + $error = 'Expected %s, found %s'; + $fix = $phpcsFile->addFixableError($error, $tag, 'DataProviderInvalidCase', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($tag, '@dataProvider'); + } + } + + $star = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $tag - 1); + $indent = ''; + $prevLine = $star; + while ($tokens[$prevLine]['line'] === $tokens[$tag]['line']) { + if ($tokens[$prevLine]['code'] === T_DOC_COMMENT_WHITESPACE) { + $indent = $tokens[$prevLine]['content']; + break; + } + --$prevLine; + } + + // Find non-empty token before @dataProvider tag. + $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR], $tag - 1, null, true); + if ($tokens[$prev]['code'] !== T_DOC_COMMENT_OPEN_TAG + && $tokens[$prev]['line'] === $tokens[$tag]['line'] - 1 + ) { + if (! isset($tags[$pos - 1]) + || strtolower($tokens[$tags[$pos - 1]]['content']) !== '@dataprovider' + ) { + $error = 'Missing blank line before @dataProvider tag.'; + $fix = $phpcsFile->addFixableError($error, $tag, 'DataProviderBlankLineBefore'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->addContent($prev, $indent . '*'); + $phpcsFile->fixer->endChangeset(); + } + } + } elseif ($tokens[$prev]['line'] < $tokens[$tag]['line'] - 1 + && isset($tags[$pos - 1]) + && strtolower($tokens[$tags[$pos - 1]]['content']) === '@dataprovider' + ) { + $error = 'Empty line between @dataProvider tags is not allowed.'; + $fix = $phpcsFile->addFixableError($error, $tag, 'DataProviderNoEmptyLineBetween'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $tag; $i > $prev + 1; --$i) { + if ($tokens[$i]['line'] === $tokens[$tag]['line']) { + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->endChangeset(); + } + } + + // Find first token in next line. + $nextLine = $tag; + while ($tokens[$nextLine]['line'] === $tokens[$tag]['line']) { + ++$nextLine; + } + + // Find non-empty token starting from next line. + $next = $phpcsFile->findNext([T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR], $nextLine, null, true); + if ($tokens[$next]['line'] === $tokens[$tag]['line'] + 1 + && $tokens[$next]['code'] !== T_DOC_COMMENT_CLOSE_TAG + ) { + if (! isset($tags[$pos + 1]) + || $next !== $tags[$pos + 1] + || strtolower($tokens[$next]['content']) !== '@dataprovider' + ) { + $error = 'Missing blank line after @dataProvider tag.'; + $fix = $phpcsFile->addFixableError($error, $tag, 'DataProviderBlankLineAfter'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewlineBefore($nextLine); + $phpcsFile->fixer->addContent($nextLine - 1, $indent . '*'); + $phpcsFile->fixer->endChangeset(); + } + } + } + } + } + /** * Process the function parameter comments. * @@ -297,6 +464,7 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) } } + $this->processDataProvider($phpcsFile, $stackPtr, $commentStart); $tokens = $phpcsFile->getTokens(); $params = []; diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc b/test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc new file mode 100644 index 00000000..39d80dcb --- /dev/null +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc @@ -0,0 +1,71 @@ + 2, + 9 => 1, + 17 => 2, + 26 => 1, + 33 => 1, + 35 => 2, + 49 => 1, + 50 => 1, + 57 => 1, + 66 => 1, + ]; + } + return [ 10 => 1, 16 => 1, From e3595e032c82ddf75dd8c5971b2b3ed49d14acbe Mon Sep 17 00:00:00 2001 From: webimpress Date: Sat, 3 Jun 2017 16:08:17 +0200 Subject: [PATCH 058/225] Fix order of statements inside trait's curly brackets --- .../Sniffs/Classes/TraitUsageSniff.php | 68 ++++++++++++++++++- .../Classes/TraitUsageUnitTest.inc.fixed | 4 +- test/Sniffs/Classes/TraitUsageUnitTest.php | 1 + 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php index 3043137a..6fff967c 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php @@ -173,6 +173,42 @@ public function process(File $phpcsFile, $stackPtr) $phpcsFile->fixer->endChangeset(); } } + + // Detect all statements inside curly brackets. + $statements = []; + $begin = $phpcsFile->findNext(Tokens::$emptyTokens, $scopeOpener + 1, null, true); + while ($end = $phpcsFile->findNext([T_SEMICOLON], $begin + 1, $scopeCloser)) { + $statements[] = [ + 'begin' => $begin, + 'end' => $end, + 'content' => $phpcsFile->getTokensAsString($begin, $end - $begin + 1), + ]; + $begin = $phpcsFile->findNext(Tokens::$emptyTokens, $end + 1, null, true); + } + + $lastStatement = null; + foreach ($statements as $statement) { + if (! $lastStatement) { + $lastStatement = $statement; + continue; + } + + $order = strnatcasecmp($statement['content'], $lastStatement['content']); + + if ($order < 0) { + $error = 'Statements in trait are incorrectly ordered. The first wrong is %s'; + $data = [$statement['content']]; + $fix = $phpcsFile->addFixableError($error, $statement['begin'], 'TraitStatementsOrder', $data); + + if ($fix) { + $this->fixAlphabeticalOrder($phpcsFile, $statements); + } + + break; + } + + $lastStatement = $statement; + } } else { $scopeCloser = $scopeOpener; } @@ -193,8 +229,6 @@ public function process(File $phpcsFile, $stackPtr) return; } - // todo: check order of statements in curly brackets - // Find next (after traits) non-whitespace token. $next = $phpcsFile->findNext(T_WHITESPACE, $scopeCloser + 1, null, true); @@ -224,4 +258,34 @@ public function process(File $phpcsFile, $stackPtr) } } } + + /** + * Fix order of statements inside trait's curly brackets. + * + * @param File $phpcsFile + * @param array $statements + * @return void + */ + private function fixAlphabeticalOrder(File $phpcsFile, array $statements) + { + $phpcsFile->fixer->beginChangeset(); + foreach ($statements as $statement) { + for ($i = $statement['begin']; $i <= $statement['end']; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + usort($statements, function (array $a, array $b) { + return strnatcasecmp($a['content'], $b['content']); + }); + + $begins = array_column($statements, 'begin'); + sort($begins); + + foreach ($begins as $k => $begin) { + $phpcsFile->fixer->addContent($begin, $statements[$k]['content']); + } + + $phpcsFile->fixer->endChangeset(); + } } diff --git a/test/Sniffs/Classes/TraitUsageUnitTest.inc.fixed b/test/Sniffs/Classes/TraitUsageUnitTest.inc.fixed index e35d24e5..a7497032 100644 --- a/test/Sniffs/Classes/TraitUsageUnitTest.inc.fixed +++ b/test/Sniffs/Classes/TraitUsageUnitTest.inc.fixed @@ -19,8 +19,8 @@ use YTrait ; use \A; use \B { - \B::smallTalk insteadof \A; - \A::bigTalk insteadof \B; + \A::bigTalk insteadof \B; + \B::smallTalk insteadof \A; } use HelloWorld { sayHello as protected; diff --git a/test/Sniffs/Classes/TraitUsageUnitTest.php b/test/Sniffs/Classes/TraitUsageUnitTest.php index 20b7678c..51ee187f 100644 --- a/test/Sniffs/Classes/TraitUsageUnitTest.php +++ b/test/Sniffs/Classes/TraitUsageUnitTest.php @@ -14,6 +14,7 @@ public function getErrorList() 15 => 2, 17 => 1, 20 => 2, + 22 => 1, 25 => 3, 26 => 4, 35 => 1, From 7c93e753abc5225e9f958d9891d1ecf45801cd07 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sat, 3 Jun 2017 16:10:18 +0200 Subject: [PATCH 059/225] Updated to latest version of PHPUnit 6.2.1 --- composer.json | 2 +- composer.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index f756fada..e03198ca 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "squizlabs/php_codesniffer": "3.0.0" }, "require-dev": { - "phpunit/phpunit": "^6.1.4 || ^5.7.20" + "phpunit/phpunit": "^6.2.1 || ^5.7.20" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 12a7f8e6..0153e399 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "43a686d3157db48ed076a5092e66e526", + "content-hash": "b754e64a4a10f0056246ad4207c082ce", "packages": [ { "name": "squizlabs/php_codesniffer", From 804c3fcc1b9f8bfac71746d79f4d7bda79bc9112 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 4 Jun 2017 10:12:21 +0200 Subject: [PATCH 060/225] Tag `@dataProvider` should be above `@param` tag(s), not necessarily as first --- .../Sniffs/Commenting/FunctionCommentSniff.php | 8 ++++---- .../Sniffs/Commenting/FunctionCommentUnitTest.1.inc.fixed | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 26d990d3..7cf2a253 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -324,12 +324,12 @@ protected function processDataProvider(File $phpcsFile, $stackPtr, $commentStart } } - // Check if @dataProvider tag is first tag. + // Check if @dataProvider tag is above @param tag(s). for ($i = $pos - 1; $i >= 0; --$i) { $prevTag = $tags[$i]; - if (strtolower($tokens[$prevTag]['content']) !== '@dataprovider') { - $error = 'Tag @dataProvider must be first tag in function comment.'; - $fix = $phpcsFile->addFixableError($error, $tag, 'DataProviderNotFirstTag'); + if (strtolower($tokens[$prevTag]['content']) === '@param') { + $error = 'Tag @dataProvider must be above @param tag(s).'; + $fix = $phpcsFile->addFixableError($error, $tag, 'DataProviderNotAboveParams'); if ($fix) { $first = $last = $tag; diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc.fixed b/test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc.fixed index 431171d4..fda986e2 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc.fixed +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc.fixed @@ -44,10 +44,11 @@ class Foo extends \PHPUnit\Framework\TestCase } /** + * @small + * * @dataProvider dataProvider6 * @dataProvider dataProvider7 * - * @small * @param string $x This is description * of the first param * @return void From ea77ed6942c561740c507d87506fbd3293dcde22 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 4 Jun 2017 22:56:24 +0200 Subject: [PATCH 061/225] Array/FormatSniff fix Correct indent of closing bracket in multiline array --- src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php | 11 +++++++++++ test/Sniffs/Arrays/FormatUnitTest.inc | 5 +++++ test/Sniffs/Arrays/FormatUnitTest.inc.fixed | 5 +++++ test/Sniffs/Arrays/FormatUnitTest.php | 1 + 4 files changed, 22 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index 9e85da16..092950b1 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -176,6 +176,17 @@ private function multiLineArray(File $phpcsFile, $stackPtr) $phpcsFile->fixer->addNewlineBefore($bracketCloser); $phpcsFile->fixer->endChangeset(); } + } elseif ($first === $bracketCloser - 1 + && $tokens[$first]['code'] === T_WHITESPACE + && strlen($tokens[$first]['content']) !== $indent + ) { + $error = 'Expected %d spaces; found %d'; + $data = [$indent, strlen($tokens[$first]['content'])]; + $fix = $phpcsFile->addFixableError($error, $first, 'CloseBracketIndent', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($first, str_repeat(' ', $indent)); + } } } } diff --git a/test/Sniffs/Arrays/FormatUnitTest.inc b/test/Sniffs/Arrays/FormatUnitTest.inc index 12c255fd..4e33020f 100644 --- a/test/Sniffs/Arrays/FormatUnitTest.inc +++ b/test/Sniffs/Arrays/FormatUnitTest.inc @@ -75,3 +75,8 @@ $arr = [ 'elem', 'elem', ]; + +$a = array_merge([ + ['a' => 'b'], + ['c' => 'd'], + ]); diff --git a/test/Sniffs/Arrays/FormatUnitTest.inc.fixed b/test/Sniffs/Arrays/FormatUnitTest.inc.fixed index 42e3e627..dabb47a4 100644 --- a/test/Sniffs/Arrays/FormatUnitTest.inc.fixed +++ b/test/Sniffs/Arrays/FormatUnitTest.inc.fixed @@ -88,3 +88,8 @@ $arr = [ 'elem', 'elem', ]; + +$a = array_merge([ + ['a' => 'b'], + ['c' => 'd'], +]); diff --git a/test/Sniffs/Arrays/FormatUnitTest.php b/test/Sniffs/Arrays/FormatUnitTest.php index 1425984f..63c4f5bd 100644 --- a/test/Sniffs/Arrays/FormatUnitTest.php +++ b/test/Sniffs/Arrays/FormatUnitTest.php @@ -39,6 +39,7 @@ public function getErrorList() 74 => 1, 75 => 1, 76 => 1, + 82 => 1, ]; } From 01388f5c079d61e5c07e9d06483c85083142647e Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 4 Jun 2017 22:57:09 +0200 Subject: [PATCH 062/225] Removed unnecessary parentheses --- .../Sniffs/Commenting/FunctionCommentSniff.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 7cf2a253..a72832df 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -644,7 +644,7 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) } $phpcsFile->addError($error, $stackPtr, $errorCode, $data); - } elseif ($typeHint !== substr($suggestedTypeHint, (strlen($typeHint) * -1))) { + } elseif ($typeHint !== substr($suggestedTypeHint, strlen($typeHint) * -1)) { $error = 'Expected type hint "%s"; found "%s" for %s'; $data = [ $suggestedTypeHint, @@ -701,7 +701,7 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) continue; } - $newIndent = ($param['commentLines'][$lineNum]['indent'] + $spaces - $param['type_space']); + $newIndent = $param['commentLines'][$lineNum]['indent'] + $spaces - $param['type_space']; $phpcsFile->fixer->replaceToken( $param['commentLines'][$lineNum]['token'] - 1, str_repeat(' ', $newIndent) @@ -770,7 +770,7 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) continue; } - $newIndent = ($param['commentLines'][$lineNum]['indent'] + $spaces - $param['var_space']); + $newIndent = $param['commentLines'][$lineNum]['indent'] + $spaces - $param['var_space']; $phpcsFile->fixer->replaceToken( $param['commentLines'][$lineNum]['token'] - 1, str_repeat(' ', $newIndent) From 61ff8af05cf79d9b9e52d4229adb2b38dcbde477 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 4 Jun 2017 23:03:12 +0200 Subject: [PATCH 063/225] New sniff: UnnecessaryParentheses This sniff replaces two sniffs: - ZendCodingStandard.Methods.ReturnValueWithourBrackets - Squiz.Strings.EchoedStrings Sniff finds and remove unnecessary parentheses, but not all of them - only these which are not breaking readability. Tested with zend-expressive and zend-code. Seems to be fine for me right now, probably it could be improved in future. --- .../UnnecessaryParenthesesSniff.php | 222 ++++++++++++++++++ .../ReturnValueWithoutBracketsSniff.php | 58 ----- src/ZendCodingStandard/ruleset.xml | 1 - .../UnnecessaryParenthesesUnitTest.inc | 148 ++++++++++++ .../UnnecessaryParenthesesUnitTest.inc.fixed | 148 ++++++++++++ .../UnnecessaryParenthesesUnitTest.php | 54 +++++ .../ReturnValueWithoutBracketsUnitTest.inc | 43 ---- ...turnValueWithoutBracketsUnitTest.inc.fixed | 43 ---- .../ReturnValueWithoutBracketsUnitTest.php | 24 -- 9 files changed, 572 insertions(+), 169 deletions(-) create mode 100644 src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php delete mode 100644 src/ZendCodingStandard/Sniffs/Methods/ReturnValueWithoutBracketsSniff.php create mode 100644 test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc create mode 100644 test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed create mode 100644 test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php delete mode 100644 test/Sniffs/Methods/ReturnValueWithoutBracketsUnitTest.inc delete mode 100644 test/Sniffs/Methods/ReturnValueWithoutBracketsUnitTest.inc.fixed delete mode 100644 test/Sniffs/Methods/ReturnValueWithoutBracketsUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php new file mode 100644 index 00000000..95fdfe23 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -0,0 +1,222 @@ +getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_owner'])) { + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); + if (in_array($tokens[$prev]['code'], $this->parenthesesAllowedTokens, true)) { + return; + } + + $closePtr = $tokens[$stackPtr]['parenthesis_closer']; + + $firstInside = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, $closePtr, true); + $lastInside = $phpcsFile->findPrevious(Tokens::$emptyTokens, $closePtr - 1, $stackPtr + 1, true); + + if ($firstInside === $lastInside) { + $this->error($phpcsFile, $stackPtr, $closePtr, 'SingleExpression'); + return; + } + + if (! in_array($tokens[$prev]['code'], Tokens::$castTokens, true)) { + $instanceOf = $phpcsFile->findNext(T_INSTANCEOF, $stackPtr + 1, $closePtr); + if ($instanceOf !== false) { + $op = $phpcsFile->findNext(Tokens::$booleanOperators, $stackPtr + 1, $closePtr); + if ($op === false) { + $this->error($phpcsFile, $stackPtr, $closePtr, 'SingleInstanceOf'); + return; + } + } + } + + if (in_array($tokens[$prev]['code'], Tokens::$operators + Tokens::$booleanOperators, true)) { + return; + } + + // Check single expression casting + if (in_array($tokens[$prev]['code'], Tokens::$castTokens, true)) { + $op = $phpcsFile->findNext( + Tokens::$assignmentTokens + + Tokens::$booleanOperators + + Tokens::$equalityTokens + + Tokens::$operators + + [ + T_INLINE_ELSE => T_INLINE_ELSE, + T_INLINE_THEN => T_INLINE_THEN, + T_INSTANCEOF => T_INSTANCEOF, + ], + $stackPtr + 1, + $closePtr + ); + + if ($op === false) { + $this->error($phpcsFile, $stackPtr, $closePtr, 'SingleCast'); + } + return; + } + + // Check single expression negation, concatenation or arithmetic operation + $prevTokens = Tokens::$arithmeticTokens + [ + T_BOOLEAN_NOT => T_BOOLEAN_NOT, + T_STRING_CONCAT => T_STRING_CONCAT, + ]; + if (in_array($tokens[$prev]['code'], $prevTokens, true)) { + $op = $phpcsFile->findNext( + Tokens::$assignmentTokens + + Tokens::$booleanOperators + + Tokens::$equalityTokens + + Tokens::$operators + + [ + T_INLINE_ELSE => T_INLINE_ELSE, + T_INLINE_THEN => T_INLINE_THEN, + ], + $stackPtr + 1, + $closePtr + ); + + if ($op === false) { + $this->error($phpcsFile, $stackPtr, $closePtr, 'SingleNot'); + } + return; + } + + // Check single expression comparision + if (in_array($tokens[$prev]['code'], Tokens::$equalityTokens, true)) { + $op = $phpcsFile->findNext( + Tokens::$assignmentTokens + + Tokens::$booleanOperators + + [ + T_BITWISE_AND => T_BITWISE_AND, + T_BITWISE_OR => T_BITWISE_OR, + T_BITWISE_XOR => T_BITWISE_XOR, + T_COALESCE => T_COALESCE, + T_INLINE_ELSE => T_INLINE_ELSE, + T_INLINE_THEN => T_INLINE_THEN, + ], + $stackPtr + 1, + $closePtr + ); + + if ($op === false) { + $this->error($phpcsFile, $stackPtr, $closePtr, 'SingleEquality'); + } + return; + } + + $endPtr = $phpcsFile->findNext($this->endTokens, $closePtr + 1); + $lastPtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $endPtr - 1, null, true); + + if ($lastPtr === $closePtr) { + // Nested ternary operator + if (in_array($tokens[$prev]['code'], [T_INLINE_THEN, T_INLINE_ELSE], true)) { + $op = $phpcsFile->findNext( + Tokens::$assignmentTokens + + Tokens::$booleanOperators + + [ + T_INLINE_ELSE => T_INLINE_ELSE, + T_INLINE_THEN => T_INLINE_THEN, + ], + $stackPtr + 1, + $closePtr + ); + + if ($op === false) { + $this->error($phpcsFile, $stackPtr, $closePtr, 'NestedTernary'); + } + return; + } + + $this->error($phpcsFile, $stackPtr, $closePtr, 'MultipleExpression'); + } + } + + /** + * @param File $phpcsFile + * @param int $openPtr + * @param int $closePtr + * @param string $errorCode + * @return void + */ + private function error(File $phpcsFile, $openPtr, $closePtr, $errorCode) + { + $tokens = $phpcsFile->getTokens(); + + $error = 'Parentheses around expression "%s" are redundant.'; + $data = [$phpcsFile->getTokensAsString($openPtr + 1, $closePtr - $openPtr - 1)]; + $fix = $phpcsFile->addFixableError($error, $openPtr, $errorCode, $data); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + if (in_array($tokens[$openPtr - 1]['code'], $this->spaceTokens, true)) { + $phpcsFile->fixer->replaceToken($openPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken($openPtr, ''); + } + $phpcsFile->fixer->replaceToken($closePtr, ''); + $phpcsFile->fixer->endChangeset(); + } + } +} diff --git a/src/ZendCodingStandard/Sniffs/Methods/ReturnValueWithoutBracketsSniff.php b/src/ZendCodingStandard/Sniffs/Methods/ReturnValueWithoutBracketsSniff.php deleted file mode 100644 index b57deaa4..00000000 --- a/src/ZendCodingStandard/Sniffs/Methods/ReturnValueWithoutBracketsSniff.php +++ /dev/null @@ -1,58 +0,0 @@ -getTokens(); - - $firstContent = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); - // If the first non-whitespace token is not an opening parenthesis, then we are not concerned. - if ($tokens[$firstContent]['code'] !== T_OPEN_PARENTHESIS) { - $phpcsFile->recordMetric($stackPtr, 'Brackets around returned value', 'no'); - return; - } - - // Find the end of the expression. - $end = $stackPtr; - do { - $end = $phpcsFile->findNext([T_SEMICOLON, T_CLOSE_TAG], $end + 1, null, false); - } while ($tokens[$end]['level'] !== $tokens[$stackPtr]['level']); - - // If the token before the semi-colon is not a closing parenthesis, then we are not concerned. - $prev = $phpcsFile->findPrevious(T_WHITESPACE, $end - 1, null, true); - if ($tokens[$prev]['code'] !== T_CLOSE_PARENTHESIS) { - $phpcsFile->recordMetric($stackPtr, 'Brackets around returned value', 'no'); - return; - } - - // If the parenthesis don't match, then we are not concerned. - if ($tokens[$firstContent]['parenthesis_closer'] !== $prev) { - $phpcsFile->recordMetric($stackPtr, 'Brackets around returned value', 'no'); - return; - } - - $phpcsFile->recordMetric($stackPtr, 'Brackets around returned value', 'yes'); - - $error = 'Returned value should not be bracketed'; - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'HasBracket'); - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->replaceToken($firstContent, ''); - if ($tokens[$firstContent - 1]['code'] !== T_WHITESPACE) { - $phpcsFile->fixer->addContent($firstContent - 1, ' '); - } - $phpcsFile->fixer->replaceToken($prev, ''); - $phpcsFile->fixer->endChangeset(); - } - } -} diff --git a/src/ZendCodingStandard/ruleset.xml b/src/ZendCodingStandard/ruleset.xml index 511ec2d6..fe4e7b48 100755 --- a/src/ZendCodingStandard/ruleset.xml +++ b/src/ZendCodingStandard/ruleset.xml @@ -49,7 +49,6 @@ Variable "%s" not allowed in double quoted string; use sprintf() instead. - diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc new file mode 100644 index 00000000..e1f7beaa --- /dev/null +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc @@ -0,0 +1,148 @@ +method2((1 + 2), 2, 3); + $arr = [ + (1 + 2) => 14, + (2 + 3) * 2 => (1 + (4 * 3)), + 34 % (2) => 1 / (2 * 3), + 8 - (1) => 7 * (4), + 1 * (4 - 2) => 2, + (11) << (2) => (5) | (6 - 2), + ]; + sort($arr); + + $i1 = new self(); + $i2 = new static(); + $i3 = new DateTime(); + + $anonym = new class() extends UnnecessaryParentheses { + }; + + $v1 = new $anonym(); + $v2 = $arr(); + $v3 = static::method4(); + $v5 = self::method4(); + $v6 = $this->{$arr}($i1); + + $i = (32 * 1); + $k = ($i + 1) << 3; + $j = ($k) ? ($i + 2) : ($i - 2) / 2; + + return('hello'); + } + + public function method2($x, $y, $z) + { + switch ($x) { + case (true): + break; + case (1): + break; + } + + return (($x || $y) && ($z)); + } + + public function method3($x, $y, $z) + { + return ($x && $y) || ($z); + } + + public static function method4() + { + for ($i = (1 + 2); ($i < 15); (++$i)) { + $i /= (2.5 + 2); + echo($i << 3); + } + + echo ($i), ($i - 1), ($i + 1), ($i - 1) * 2; + + return (function() use ($i) { + return ('foo'); + }); + } + + public function method5() + { + return (function() { + return('bar'); + })(); + } + + public function method6() + { + if (isset($x)) { + if (empty($y)) { + unset($x); + unset($a, $b); + } + + exit($x); + } + + $c = eval('function(){}'); + + return (1 + 2); + } + + private function method7($x) + { + while (($x)) { + $x = abs((--$x)); + if (($x) % 19) { + die($x); + } + } + + return (1 + 2) * 3; + } + + protected function method8($x, $y) + { + if (! ($x || $y)) { + if (! ($x) || ! ($x + $y)) { + echo $x, ($y); + } + } + + $z = ! ($x instanceof DateTime || ($x) instanceof ArrayAccess); + + return(1 / ($z ? 2 : 3)); + } + + public function method9($x, $y) + { + if (false === ($a = strpos($x, $y))) { + return (3 ^ $a); + } + + if (($b = strpos($x, $y)) != false) { + return [$a, ($b - 2)]; + } + + $h = (int) ($a instanceof DateTime); + $m = (int) ($a + $b); + $n = (float) ($b); + $w = (bool) ($x ^ $y); + $z = (null === ($x ?: null)); + $q = 'string' + . (! empty($x) ? ' ' . $x : '') + . (! empty($y) ? ' ' . $y : ''); + $r = 1 + ($x ? 2 : 3); + $s = (! (($x instanceof DateTime) || ($x instanceof ArrayAccess))); + $p = $x ?: ($y ?: (2 + 1)); + $o = $x ? ($y ?: 1) : ($x - 1); + + return(! ($b || $a) || ($a - $b)); + } + + public function method10($a, $b, $c) + { + if (($a || $z = strpos($b, $c)) === false) { + } + } +} diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed new file mode 100644 index 00000000..c4c07d82 --- /dev/null +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed @@ -0,0 +1,148 @@ +method2(1 + 2, 2, 3); + $arr = [ + 1 + 2 => 14, + (2 + 3) * 2 => 1 + (4 * 3), + 34 % 2 => 1 / (2 * 3), + 8 - 1 => 7 * 4, + 1 * (4 - 2) => 2, + 11 << 2 => 5 | (6 - 2), + ]; + sort($arr); + + $i1 = new self(); + $i2 = new static(); + $i3 = new DateTime(); + + $anonym = new class() extends UnnecessaryParentheses { + }; + + $v1 = new $anonym(); + $v2 = $arr(); + $v3 = static::method4(); + $v5 = self::method4(); + $v6 = $this->{$arr}($i1); + + $i = 32 * 1; + $k = ($i + 1) << 3; + $j = $k ? $i + 2 : ($i - 2) / 2; + + return 'hello'; + } + + public function method2($x, $y, $z) + { + switch ($x) { + case true: + break; + case 1: + break; + } + + return ($x || $y) && $z; + } + + public function method3($x, $y, $z) + { + return ($x && $y) || $z; + } + + public static function method4() + { + for ($i = 1 + 2; $i < 15; ++$i) { + $i /= 2.5 + 2; + echo $i << 3; + } + + echo $i, $i - 1, $i + 1, ($i - 1) * 2; + + return function() use ($i) { + return 'foo'; + }; + } + + public function method5() + { + return (function() { + return 'bar'; + })(); + } + + public function method6() + { + if (isset($x)) { + if (empty($y)) { + unset($x); + unset($a, $b); + } + + exit($x); + } + + $c = eval('function(){}'); + + return 1 + 2; + } + + private function method7($x) + { + while ($x) { + $x = abs(--$x); + if ($x % 19) { + die($x); + } + } + + return (1 + 2) * 3; + } + + protected function method8($x, $y) + { + if (! ($x || $y)) { + if (! $x || ! ($x + $y)) { + echo $x, $y; + } + } + + $z = ! ($x instanceof DateTime || $x instanceof ArrayAccess); + + return 1 / ($z ? 2 : 3); + } + + public function method9($x, $y) + { + if (false === ($a = strpos($x, $y))) { + return 3 ^ $a; + } + + if (($b = strpos($x, $y)) != false) { + return [$a, $b - 2]; + } + + $h = (int) ($a instanceof DateTime); + $m = (int) ($a + $b); + $n = (float) $b; + $w = (bool) ($x ^ $y); + $z = null === ($x ?: null); + $q = 'string' + . (! empty($x) ? ' ' . $x : '') + . (! empty($y) ? ' ' . $y : ''); + $r = 1 + ($x ? 2 : 3); + $s = ! ($x instanceof DateTime || $x instanceof ArrayAccess); + $p = $x ?: ($y ?: 2 + 1); + $o = $x ? ($y ?: 1) : $x - 1; + + return ! ($b || $a) || ($a - $b); + } + + public function method10($a, $b, $c) + { + if (($a || $z = strpos($b, $c)) === false) { + } + } +} diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php new file mode 100644 index 00000000..23d3189b --- /dev/null +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php @@ -0,0 +1,54 @@ + 1, + 9 => 1, + 10 => 1, + 11 => 1, + 12 => 2, + 14 => 3, + 31 => 1, + 33 => 2, + 35 => 1, + 41 => 1, + 43 => 1, + 47 => 2, + 52 => 1, + 57 => 3, + 58 => 1, + 59 => 1, + 62 => 3, + 64 => 1, + 65 => 1, + 72 => 1, + 89 => 1, + 94 => 1, + 95 => 1, + 96 => 1, + 107 => 1, + 108 => 1, + 112 => 1, + 114 => 1, + 120 => 1, + 124 => 1, + 129 => 1, + 131 => 1, + 136 => 3, + 137 => 1, + 138 => 1, + 140 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} diff --git a/test/Sniffs/Methods/ReturnValueWithoutBracketsUnitTest.inc b/test/Sniffs/Methods/ReturnValueWithoutBracketsUnitTest.inc deleted file mode 100644 index dedf1d6d..00000000 --- a/test/Sniffs/Methods/ReturnValueWithoutBracketsUnitTest.inc +++ /dev/null @@ -1,43 +0,0 @@ - 1, - 12 => 1, - 22 => 1, - 23 => 1, - 30 => 1, - 36 => 1, - ]; - } - - public function getWarningList($testFile = '') - { - return []; - } -} From 4b34eb96d6d8c87839b8a1f6a4e97838f60aca2b Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 4 Jun 2017 23:26:00 +0200 Subject: [PATCH 064/225] PHPDocs consistency - use `@inheritDoc` tag --- src/ZendCodingStandard/CodingStandard.php | 9 +++++ .../Sniffs/Arrays/FormatSniff.php | 6 +-- .../Sniffs/Arrays/TrailingArrayCommaSniff.php | 6 +-- .../AlphabeticallySortedTraitsSniff.php | 6 +-- .../Sniffs/Classes/TraitUsageSniff.php | 6 +-- .../Sniffs/Commenting/DocCommentSniff.php | 6 +-- .../Commenting/FunctionCommentSniff.php | 24 ++--------- .../Commenting/VariableCommentSniff.php | 40 ++----------------- .../Sniffs/Formatting/DoubleColonSniff.php | 6 +-- .../Sniffs/Formatting/NewKeywordSniff.php | 6 +-- .../Formatting/NoSpaceAfterSplatSniff.php | 6 +-- .../Sniffs/Methods/LineAfterSniff.php | 19 +++------ .../AlphabeticallySortedUsesSniff.php | 6 +-- .../ConstAndFunctionKeywordsSniff.php | 6 +-- .../Namespaces/UnusedUseStatementSniff.php | 14 +------ .../UseDoesNotStartWithBackslashSniff.php | 6 +-- .../ValidVariableNameSniff.php | 9 ++--- ...gicalOperatorNotAtTheEndOfTheLineSniff.php | 6 +-- .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 6 +-- .../PHP/InstantiatingParenthesisSniff.php | 6 +-- .../Sniffs/PHP/LowerCaseKeywordSniff.php | 3 ++ .../Sniffs/PHP/RedundantSemicolonSniff.php | 6 +-- .../Sniffs/PHP/TypeCastingSniff.php | 32 +-------------- .../Strings/NoConcatenationAtTheEndSniff.php | 6 +++ .../Sniffs/WhiteSpace/BlankLineSniff.php | 6 +-- .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 6 +-- .../WhiteSpace/NoBlankLineAtStartSniff.php | 6 +-- 27 files changed, 72 insertions(+), 192 deletions(-) diff --git a/src/ZendCodingStandard/CodingStandard.php b/src/ZendCodingStandard/CodingStandard.php index 75d2fff7..ff4eba7e 100644 --- a/src/ZendCodingStandard/CodingStandard.php +++ b/src/ZendCodingStandard/CodingStandard.php @@ -19,6 +19,15 @@ class CodingStandard 'callable', ]; + /** + * Returns a valid variable type for param/var tag. + * + * If type is not one of the standard type, it must be a custom type. + * Returns the correct type name suggestion if type name is invalid. + * + * @param string $varType The variable type to process. + * @return string + */ public static function suggestType($varType) { $lowerVarType = strtolower($varType); diff --git a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index 092950b1..96e67b6f 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -14,7 +14,7 @@ class FormatSniff implements Sniff public $indent = 4; /** - * @return int[] + * @inheritDoc */ public function register() { @@ -22,9 +22,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php index 66147055..55ca4496 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php @@ -11,7 +11,7 @@ class TrailingArrayCommaSniff implements Sniff { /** - * @return int[] + * @inheritDoc */ public function register() { @@ -19,9 +19,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php index 6066a9ec..9403aadc 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php @@ -8,7 +8,7 @@ class AlphabeticallySortedTraitsSniff implements Sniff { /** - * @return int[] + * @inheritDoc */ public function register() { @@ -16,9 +16,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php index 6fff967c..3383e228 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php @@ -9,7 +9,7 @@ class TraitUsageSniff implements Sniff { /** - * @return int[] + * @inheritDoc */ public function register() { @@ -17,9 +17,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index e3c00386..64c663a0 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -7,7 +7,7 @@ class DocCommentSniff implements Sniff { /** - * @return int[] + * @inheritDoc */ public function register() { @@ -15,9 +15,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index a72832df..66203463 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -23,13 +23,7 @@ class FunctionCommentSniff extends PEARFunctionCommentSniff private $hasInheritDoc = []; /** - * Process the return comment of this function comment. - * - * @param File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. - * @param int $commentStart The position in the stack where the comment started. - * @return void + * @inheritDoc */ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) { @@ -151,13 +145,7 @@ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) } /** - * Process any throw tags that this function comment has. - * - * @param File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. - * @param int $commentStart The position in the stack where the comment started. - * @return void + * @inheritDoc */ protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) { @@ -447,13 +435,7 @@ protected function processDataProvider(File $phpcsFile, $stackPtr, $commentStart } /** - * Process the function parameter comments. - * - * @param File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. - * @param int $commentStart The position in the stack where the comment started. - * @return void + * @inheritDoc */ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) { diff --git a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php index 58947341..8fd7b050 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php @@ -11,28 +11,10 @@ use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; use ZendCodingStandard\CodingStandard; -/** - * Parses and verifies the variable doc comment. - * - * @category PHP - * @package PHP_CodeSniffer - * @author Greg Sherwood - * @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 - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer - */ class VariableCommentSniff extends AbstractVariableSniff { /** - * Called to process class member vars. - * - * @param File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. - * - * @return void + * @inheritDoc */ public function processMemberVar(File $phpcsFile, $stackPtr) { @@ -129,30 +111,14 @@ public function processMemberVar(File $phpcsFile, $stackPtr) } /** - * Called to process a normal variable. - * - * Not required for this sniff. - * - * @param File $phpcsFile The PHP_CodeSniffer file where this token was found. - * @param int $stackPtr The position where the double quoted - * string was found. - * - * @return void + * @inheritDoc */ protected function processVariable(File $phpcsFile, $stackPtr) { } /** - * Called to process variables found in double quoted strings. - * - * Not required for this sniff. - * - * @param File $phpcsFile The PHP_CodeSniffer file where this token was found. - * @param int $stackPtr The position where the double quoted - * string was found. - * - * @return void + * @inheritDoc */ protected function processVariableInString(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php index 56a17e40..6c654120 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php @@ -7,7 +7,7 @@ class DoubleColonSniff implements Sniff { /** - * @return array + * @inheritDoc */ public function register() { @@ -15,9 +15,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php index 9ec84744..9cd9440d 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php @@ -7,7 +7,7 @@ class NewKeywordSniff implements Sniff { /** - * @return array + * @inheritDoc */ public function register() { @@ -15,9 +15,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php index a2c88bd4..d67e8fe7 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php @@ -7,7 +7,7 @@ class NoSpaceAfterSplatSniff implements Sniff { /** - * @return array + * @inheritDoc */ public function register() { @@ -15,9 +15,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php index 0e51e76d..b8c30213 100644 --- a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php +++ b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php @@ -1,7 +1,4 @@ - * @copyright 2016 Capstone Digital - */ class UnusedUseStatementSniff implements Sniff { /** - * @return int[] + * @inheritDoc */ public function register() { @@ -34,9 +26,7 @@ public function register() } /** - * @param File $phpcsFile The - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php index 009f4c3a..e2c33bb2 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php @@ -9,7 +9,7 @@ class UseDoesNotStartWithBackslashSniff implements Sniff { /** - * @return int[] + * @inheritDoc */ public function register() { @@ -17,9 +17,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php index bb77f303..a934e3b0 100644 --- a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php +++ b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -28,8 +28,7 @@ class ValidVariableNameSniff extends AbstractVariableSniff ]; /** - * @param File $phpcsFile - * @param int $stackPtr Position of the double quoted string. + * @inheritDoc */ protected function processVariable(File $phpcsFile, $stackPtr) { @@ -54,8 +53,7 @@ protected function processVariable(File $phpcsFile, $stackPtr) } /** - * @param File $phpcsFile - * @param int $stackPtr Position of the double quoted string. + * @inheritDoc */ protected function processMemberVar(File $phpcsFile, $stackPtr) { @@ -63,8 +61,7 @@ protected function processMemberVar(File $phpcsFile, $stackPtr) } /** - * @param File $phpcsFile - * @param int $stackPtr Position of the double quoted string. + * @inheritDoc */ protected function processVariableInString(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php b/src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php index 6b209998..05db4b19 100644 --- a/src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php +++ b/src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php @@ -8,7 +8,7 @@ class LogicalOperatorNotAtTheEndOfTheLineSniff implements Sniff { /** - * @return int[] + * @inheritDoc */ public function register() { @@ -16,9 +16,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index 08cb0c03..d6717b93 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -27,7 +27,7 @@ public function __construct() } /** - * @return int[] + * @inheritDoc */ public function register() { @@ -41,9 +41,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php index 39468d1e..50f8f33d 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php @@ -8,7 +8,7 @@ class InstantiatingParenthesisSniff implements Sniff { /** - * @return array + * @inheritDoc */ public function register() { @@ -16,9 +16,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php b/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php index 48457c26..30d2cfa2 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php @@ -5,6 +5,9 @@ class LowerCaseKeywordSniff extends GenericLowerCaseKeywordSniff { + /** + * @inheritDoc + */ public function register() { return array_merge( diff --git a/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php b/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php index 6235bdc4..8554f6d1 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php @@ -8,7 +8,7 @@ class RedundantSemicolonSniff implements Sniff { /** - * @return int[] + * @inheritDoc */ public function register() { @@ -16,9 +16,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php index 56315d4f..0090debd 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -14,33 +14,10 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; -/** - * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) - * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) - * - * Licensed under The MIT License - * For full copyright and license information, please see the LICENSE.txt - * Redistributions of files must retain the above copyright notice. - * - * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) - * @link http://pear.php.net/package/PHP_CodeSniffer_CakePHP - * @license http://www.opensource.org/licenses/mit-license.php MIT License - * - * Asserts that type casts are in the short form: - * - bool instead of boolean - * - int instead of integer - */ class TypeCastingSniff implements Sniff { /** - * Returns an array of tokens this test wants to listen for. - * - * Note, that this sniff only checks the value and casing of a cast. - * It does not check for whitespace issues regarding casts, as - * - Squiz.WhiteSpace.CastSpacing.ContainsWhiteSpace checks for whitespace in the cast - * - Generic.Formatting.NoSpaceAfterCast.SpaceFound checks for whitespace after the cast - * - * @return array + * @inheritDoc */ public function register() { @@ -48,12 +25,7 @@ public function register() } /** - * Processes this test, when one of its tokens is encountered. - * - * @param File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token in the - * stack passed in $tokens. - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php b/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php index 5c2c8556..efa6681d 100644 --- a/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php +++ b/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php @@ -6,11 +6,17 @@ class NoConcatenationAtTheEndSniff implements Sniff { + /** + * @inheritDoc + */ public function register() { return [T_STRING_CONCAT]; } + /** + * @inheritDoc + */ public function process(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php index 1a056294..accfa2b6 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php @@ -7,7 +7,7 @@ class BlankLineSniff implements Sniff { /** - * @return int[] + * @inheritDoc */ public function register() { @@ -19,9 +19,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index 36b7e591..139a69db 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -21,7 +21,7 @@ class CommaSpacingSniff implements Sniff { /** - * @return int[] + * @inheritDoc */ public function register() { @@ -29,9 +29,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php index 9422a156..96ed37f8 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php @@ -7,7 +7,7 @@ class NoBlankLineAtStartSniff implements Sniff { /** - * @return int[] + * @inheritDoc */ public function register() { @@ -21,9 +21,7 @@ public function register() } /** - * @param File $phpcsFile - * @param int $stackPtr - * @return void + * @inheritDoc */ public function process(File $phpcsFile, $stackPtr) { From efe3d0de7c056b778c2eb5cf1cb37c3a982ea6e0 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 4 Jun 2017 23:26:32 +0200 Subject: [PATCH 065/225] Strict comparisons --- .../Sniffs/Namespaces/UnusedUseStatementSniff.php | 8 ++++---- src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index 0f2613f5..8c05da62 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -107,14 +107,14 @@ public function process(File $phpcsFile, $stackPtr) unset($emptyTokens[T_DOC_COMMENT_TAG]); while ($classUsed !== false) { - if (($tokens[$classUsed]['code'] == T_STRING + if (($tokens[$classUsed]['code'] === T_STRING && strtolower($tokens[$classUsed]['content']) === $lowerClassName) - || ($tokens[$classUsed]['code'] == T_DOC_COMMENT_STRING + || ($tokens[$classUsed]['code'] === T_DOC_COMMENT_STRING && preg_match( '/(\s|\||^)' . preg_quote($lowerClassName) . '(\s|\||\\\\|$|\[\])/i', $tokens[$classUsed]['content'] )) - || ($tokens[$classUsed]['code'] == T_DOC_COMMENT_TAG + || ($tokens[$classUsed]['code'] === T_DOC_COMMENT_TAG && preg_match( '/@' . preg_quote($lowerClassName) . '(\(|\\\\|$)/i', $tokens[$classUsed]['content'] @@ -127,7 +127,7 @@ public function process(File $phpcsFile, $stackPtr) true ); - if ($tokens[$classUsed]['code'] == T_STRING) { + if ($tokens[$classUsed]['code'] === T_STRING) { // If a backslash is used before the class name then this is some other // use statement. if ($tokens[$beforeUsage]['code'] !== T_USE diff --git a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php index 0090debd..64d988ba 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -32,9 +32,9 @@ public function process(File $phpcsFile, $stackPtr) $tokens = $phpcsFile->getTokens(); // Process !! casts - if ($tokens[$stackPtr]['code'] == T_BOOLEAN_NOT) { + if ($tokens[$stackPtr]['code'] === T_BOOLEAN_NOT) { $nextToken = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); - if ($tokens[$nextToken]['code'] != T_BOOLEAN_NOT) { + if ($tokens[$nextToken]['code'] !== T_BOOLEAN_NOT) { return; } $error = 'Usage of !! cast is not allowed. Please use (bool) to cast.'; @@ -50,7 +50,7 @@ public function process(File $phpcsFile, $stackPtr) return; } - if ($tokens[$stackPtr]['code'] == T_UNSET_CAST) { + if ($tokens[$stackPtr]['code'] === T_UNSET_CAST) { $phpcsFile->addError('(unset) casting is not allowed.', $stackPtr, 'UnsetCast'); return; } From eabea35617bc945bd2024604c9861b0ba1aec216 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 4 Jun 2017 23:26:40 +0200 Subject: [PATCH 066/225] Removed unused variable --- .../Sniffs/Commenting/FunctionCommentSniff.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 66203463..25a54574 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -151,7 +151,6 @@ protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) { $tokens = $phpcsFile->getTokens(); - $throws = []; foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { if ($tokens[$tag]['content'] !== '@throws') { continue; From dfb80c8af6de865fb37cf8363ef8bff59fc476cf Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 4 Jun 2017 23:38:56 +0200 Subject: [PATCH 067/225] Improvements of FunctionComment sniff After changing PHPDocs noticed that values stored in property are from all scaned files, not just from the one file. This is why key must be specific for the file and stack ptr, not only to the stack ptr. --- .../Sniffs/Commenting/FunctionCommentSniff.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 25a54574..114a546d 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -215,8 +215,10 @@ protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) */ protected function hasInheritDocTag(File $phpcsFile, $stackPtr, $commentStart) { - if (isset($this->hasInheritDoc[$stackPtr])) { - return $this->hasInheritDoc[$stackPtr]; + $id = spl_object_hash($phpcsFile) . ':' . $stackPtr; + + if (isset($this->hasInheritDoc[$id])) { + return $this->hasInheritDoc[$id]; } $tokens = $phpcsFile->getTokens(); @@ -241,8 +243,8 @@ protected function hasInheritDocTag(File $phpcsFile, $stackPtr, $commentStart) } } - $this->hasInheritDoc[$stackPtr] = true; - return $this->hasInheritDoc[$stackPtr]; + $this->hasInheritDoc[$id] = true; + return $this->hasInheritDoc[$id]; } foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { @@ -257,13 +259,13 @@ protected function hasInheritDocTag(File $phpcsFile, $stackPtr, $commentStart) } } - $this->hasInheritDoc[$stackPtr] = true; - return $this->hasInheritDoc[$stackPtr]; + $this->hasInheritDoc[$id] = true; + return $this->hasInheritDoc[$id]; } } - $this->hasInheritDoc[$stackPtr] = false; - return $this->hasInheritDoc[$stackPtr]; + $this->hasInheritDoc[$id] = false; + return $this->hasInheritDoc[$id]; } /** From f727152bd72acc67ccd1d1d372c0736b3db7f08f Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Jun 2017 10:27:26 +0200 Subject: [PATCH 068/225] Added missing token: `T_CLONE` which does not require parentheses --- .../Sniffs/Formatting/UnnecessaryParenthesesSniff.php | 1 + test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc | 1 + test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed | 1 + test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php | 1 + 4 files changed, 4 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php index 95fdfe23..3f63cf46 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -39,6 +39,7 @@ class UnnecessaryParenthesesSniff implements Sniff ]; private $spaceTokens = [ + T_CLONE, T_ECHO, T_RETURN, T_INCLUDE, diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc index e1f7beaa..cebad8f4 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc @@ -143,6 +143,7 @@ class UnnecessaryParentheses public function method10($a, $b, $c) { if (($a || $z = strpos($b, $c)) === false) { + $z = clone($a); } } } diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed index c4c07d82..28fe32c7 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed @@ -143,6 +143,7 @@ class UnnecessaryParentheses public function method10($a, $b, $c) { if (($a || $z = strpos($b, $c)) === false) { + $z = clone $a; } } } diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php index 23d3189b..309b2d18 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php @@ -44,6 +44,7 @@ public function getErrorList($testFile = '') 137 => 1, 138 => 1, 140 => 1, + 146 => 1, ]; } From b799bcfb108a3ba1f9e7921471b98ebfff53ce54 Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Jun 2017 12:52:16 +0200 Subject: [PATCH 069/225] Allowed align values in multidimensional arrays with indexes --- .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 3 ++- test/Sniffs/WhiteSpace/CommaSpacingUnitTest.inc | 5 +++++ .../WhiteSpace/CommaSpacingUnitTest.inc.fixed | 5 +++++ test/Sniffs/WhiteSpace/CommaSpacingUnitTest.php | 16 ++++++++-------- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index 139a69db..ae99baf8 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -81,7 +81,8 @@ public function process(File $phpcsFile, $stackPtr) ); if ($tokens[$openArray]['line'] !== $tokens[$closeArray]['line'] - || $tokens[$beforeOpening]['line'] === $tokens[$openArray]['line'] + || ($tokens[$beforeOpening]['line'] === $tokens[$openArray]['line'] + && $tokens[$beforeOpening]['code'] !== T_DOUBLE_ARROW) || $tokens[$afterClosing]['line'] === $tokens[$closeArray]['line'] ) { $error = 'Expected 1 space after comma; found %d'; diff --git a/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.inc b/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.inc index 38ab6da8..d4263ad3 100644 --- a/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.inc +++ b/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.inc @@ -19,6 +19,11 @@ $arr = [ [22, 3432, 23, 4], ]; +$arr2 = [ + 'key1' => [1, 2, 3], + 'longKey' => [123, 456, 789], +]; + abstract class MyClass { public function method($x,$y, $z){} diff --git a/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.inc.fixed b/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.inc.fixed index 439000a8..9030afa8 100644 --- a/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.inc.fixed +++ b/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.inc.fixed @@ -19,6 +19,11 @@ $arr = [ [22, 3432, 23, 4], ]; +$arr2 = [ + 'key1' => [1, 2, 3], + 'longKey' => [123, 456, 789], +]; + abstract class MyClass { public function method($x, $y, $z){} diff --git a/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.php b/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.php index b928c1cd..cc5e2e90 100644 --- a/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.php +++ b/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.php @@ -14,15 +14,15 @@ public function getErrorList($testFile = '') 10 => 2, 12 => 1, 14 => 2, - 23 => 2, - 25 => 2, - 29 => 2, - 33 => 2, - 36 => 1, - 39 => 1, - 43 => 2, + 28 => 2, + 30 => 2, + 34 => 2, + 38 => 2, + 41 => 1, + 44 => 1, 48 => 2, - 49 => 3, + 53 => 2, + 54 => 3, ]; } From c85fb9834a3ae6b5d278191f25d7c972c74cd6e2 Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Jun 2017 13:29:23 +0200 Subject: [PATCH 070/225] Added Formating Reference sniff There must be one space before reference character (&) and no space after --- .../Sniffs/Formatting/ReferenceSniff.php | 58 +++++++++++++++++++ test/Sniffs/Formatting/ReferenceUnitTest.inc | 14 +++++ .../Formatting/ReferenceUnitTest.inc.fixed | 14 +++++ test/Sniffs/Formatting/ReferenceUnitTest.php | 24 ++++++++ 4 files changed, 110 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php create mode 100644 test/Sniffs/Formatting/ReferenceUnitTest.inc create mode 100644 test/Sniffs/Formatting/ReferenceUnitTest.inc.fixed create mode 100644 test/Sniffs/Formatting/ReferenceUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php new file mode 100644 index 00000000..97434970 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php @@ -0,0 +1,58 @@ +getTokens(); + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); + + $tokenCodes = Tokens::$assignmentTokens + [ + T_COMMA => T_COMMA, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_OPEN_SHORT_ARRAY => T_OPEN_SHORT_ARRAY, + ]; + if (! in_array($tokens[$prev]['code'], $tokenCodes, true)) { + return; + } + + // One space before & + if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line'] + && ! in_array($tokens[$stackPtr - 1]['code'], [T_WHITESPACE, T_OPEN_PARENTHESIS, T_OPEN_SHORT_ARRAY], true) + ) { + $error = 'Missing space before reference character'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MissingSpace'); + + if ($fix) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + } + + // No space after & + if ($tokens[$stackPtr + 1]['code'] === T_WHITESPACE) { + $error = 'Unexpected space after reference character'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UnexpectedSpace'); + + if ($fix) { + $phpcsFile->fixer->replaceToken($stackPtr + 1, ''); + } + } + } +} diff --git a/test/Sniffs/Formatting/ReferenceUnitTest.inc b/test/Sniffs/Formatting/ReferenceUnitTest.inc new file mode 100644 index 00000000..75a9d2b2 --- /dev/null +++ b/test/Sniffs/Formatting/ReferenceUnitTest.inc @@ -0,0 +1,14 @@ + 1, + 5 => 1, + 6 => 2, + 7 => 1, + 8 => 1, + 13 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From c82072a41c4be9869b45cce7ea4b14027cf7f616 Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Jun 2017 14:32:41 +0200 Subject: [PATCH 071/225] Blank line in PHPDoc after description and before tags There must be one blank line in comment after description and before comment tags --- .../Sniffs/Commenting/DocCommentSniff.php | 42 +++++++++++++++++++ test/Sniffs/Commenting/DocCommentUnitTest.inc | 15 ++++++- .../Commenting/DocCommentUnitTest.inc.fixed | 18 +++++++- test/Sniffs/Commenting/DocCommentUnitTest.php | 3 ++ 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index 64c663a0..b019ea54 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -43,6 +43,8 @@ public function process(File $phpcsFile, $stackPtr) $this->checkSpacesAfterStar($phpcsFile, $commentStart, $commentEnd); $this->checkBlankLinesInComment($phpcsFile, $commentStart, $commentEnd); + + $this->checkBlankLineBeforeTags($phpcsFile, $commentStart); } /** @@ -571,4 +573,44 @@ private function checkCommentIndents(File $phpcsFile, $commentStart, $commentEnd $from = $next; } } + + /** + * Check if there is one blank line before comment tags. + * + * @param File $phpcsFile + * @param int $commentStart + * @return void + */ + private function checkBlankLineBeforeTags(File $phpcsFile, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + if (!$tokens[$commentStart]['comment_tags']) { + return; + } + + $tag = $tokens[$commentStart]['comment_tags'][0]; + $beforeTag = $phpcsFile->findPrevious( + [T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR], + $tag - 1, + null, + true + ); + + if ($tokens[$beforeTag]['code'] === T_DOC_COMMENT_STRING + && $tokens[$beforeTag]['line'] === $tokens[$tag]['line'] - 1 + ) { + $firstOnLine = $phpcsFile->findFirstOnLine([], $tag, true); + + $error = 'Missing blank line before comment tags.'; + $fix = $phpcsFile->addFixableError($error, $firstOnLine, 'MissingBlankLine'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewlineBefore($firstOnLine); + $phpcsFile->fixer->addContentBefore($firstOnLine, '*'); + $phpcsFile->fixer->endChangeset(); + } + } + } } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc b/test/Sniffs/Commenting/DocCommentUnitTest.inc index b106f93a..438d98bf 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc @@ -6,10 +6,10 @@ namespace MyApp\MyNamespace; /** Class foo - * @package MyApp\MyNamespace * Description of the class * - OK * Indents + * @package MyApp\MyNamespace */ class Foo { @@ -121,4 +121,17 @@ class Foo /** This is another description */ $b = 1; } + + /** + * Description + * @return void + */ + public function test5() + { + /** + * Long information about the variable. + * @var string $x + */ + $x = 'something'; + } } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed index 05efaa6a..1d05d675 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed @@ -7,10 +7,11 @@ namespace MyApp\MyNamespace; /** * Class foo - * @package MyApp\MyNamespace * Description of the class * - OK * Indents + * + * @package MyApp\MyNamespace */ class Foo { @@ -118,4 +119,19 @@ $c = 'xyz'; /** This is another description */ $b = 1; } + + /** + * Description + * + * @return void + */ + public function test5() + { + /** + * Long information about the variable. + * + * @var string $x + */ + $x = 'something'; + } } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.php b/test/Sniffs/Commenting/DocCommentUnitTest.php index 90ff71d2..2ab78478 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.php +++ b/test/Sniffs/Commenting/DocCommentUnitTest.php @@ -95,6 +95,7 @@ public function getErrorList($testFile = '') return [ 3 => 1, 8 => 1, + 10 => 1, 11 => 1, 12 => 1, 13 => 1, @@ -131,6 +132,8 @@ public function getErrorList($testFile = '') 104 => 1, 110 => 1, 111 => 1, + 127 => 1, + 133 => 1, ]; } From 59aaab6e2d743695eb5d4698102645448883d6bc Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Jun 2017 14:36:07 +0200 Subject: [PATCH 072/225] VariableComment sniff skip normal comment when there is blank line after Comments // and /* are skipped in checks when there is one empty line after the comment and before variable definition. --- .../Sniffs/Commenting/VariableCommentSniff.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php index 8fd7b050..55565427 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php @@ -3,6 +3,7 @@ * Copied from Squiz_Sniffs_Commenting_VariableCommentSniff * with modifications: * - use suggested types from ZendCodingStandard\CodingStandard + * - skip normal comments if there is one blank line after the comment */ namespace ZendCodingStandard\Sniffs\Commenting; @@ -38,11 +39,10 @@ public function processMemberVar(File $phpcsFile, $stackPtr) } if ($tokens[$commentEnd]['code'] === T_COMMENT) { - $phpcsFile->addError( - 'You must use "/**" style comments for a member variable comment', - $stackPtr, - 'WrongStyle' - ); + if ($tokens[$commentEnd]['line'] === $tokens[$stackPtr]['line'] - 1) { + $error = 'You must use "/**" style comments for a member variable comment'; + $phpcsFile->addError($error, $stackPtr, 'WrongStyle'); + } return; } From 8954525e6c365c75b05dc2f38c891b38ab0afd74 Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Jun 2017 14:49:12 +0200 Subject: [PATCH 073/225] CS fixes --- src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php | 2 +- .../Sniffs/Namespaces/UnusedUseStatementSniff.php | 1 + .../Sniffs/NamingConventions/ValidVariableNameSniff.php | 1 + src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index b019ea54..a12ca221 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -585,7 +585,7 @@ private function checkBlankLineBeforeTags(File $phpcsFile, $commentStart) { $tokens = $phpcsFile->getTokens(); - if (!$tokens[$commentStart]['comment_tags']) { + if (! $tokens[$commentStart]['comment_tags']) { return; } diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index 8c05da62..589969b9 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -1,6 +1,7 @@ Date: Mon, 5 Jun 2017 15:02:43 +0200 Subject: [PATCH 074/225] One blank line after file PHPDocs --- .../Sniffs/Commenting/DocCommentSniff.php | 14 ++++++++++++-- .../Commenting/DocCommentUnitTest.4.inc.fixed | 1 + test/Sniffs/Commenting/DocCommentUnitTest.5.inc | 1 - test/Sniffs/Commenting/DocCommentUnitTest.php | 10 +++++----- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index a12ca221..205d5ab9 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -237,6 +237,7 @@ private function checkAfterClose(File $phpcsFile, $commentStart, $commentEnd) T_USE, ]; + $prev = $phpcsFile->findPrevious(T_WHITESPACE, $commentStart - 1, null, true); $next = $phpcsFile->findNext(T_WHITESPACE, $commentEnd + 1, null, true); if (! $next) { @@ -247,7 +248,7 @@ private function checkAfterClose(File $phpcsFile, $commentStart, $commentEnd) if ($tokens[$commentEnd]['line'] === $tokens[$next]['line']) { $error = 'The close comment tag must be the only content on the line.'; - $fix = $phpcsFile->addFixableError($error, $commentEnd, ''); + $fix = $phpcsFile->addFixableError($error, $commentEnd, 'ContentAfterClosingTag'); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -259,8 +260,17 @@ private function checkAfterClose(File $phpcsFile, $commentStart, $commentEnd) $phpcsFile->fixer->addNewline($newLine); $phpcsFile->fixer->endChangeset(); } + } elseif ($tokens[$prev]['code'] === T_OPEN_TAG + && $tokens[$next]['line'] === $tokens[$commentEnd]['line'] + 1 + ) { + $error = 'Missing blank line after file doc comment.'; + $fix = $phpcsFile->addFixableError($error, $commentEnd, 'MissingBlankLineAfter'); + + if ($fix) { + $phpcsFile->fixer->addNewline($commentEnd); + } } elseif ($tokens[$next]['line'] > $tokens[$commentEnd]['line'] + 1 - && ! in_array($tokens[$next]['code'], $allowEmptyLineBefore) + && ! in_array($tokens[$next]['code'], $allowEmptyLineBefore, true) ) { $error = 'Additional blank lines found after doc comment.'; $fix = $phpcsFile->addFixableError($error, $commentEnd + 2, 'BlankLinesAfter'); diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.4.inc.fixed b/test/Sniffs/Commenting/DocCommentUnitTest.4.inc.fixed index 5cf2a922..1bfb3f25 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.4.inc.fixed +++ b/test/Sniffs/Commenting/DocCommentUnitTest.4.inc.fixed @@ -2,6 +2,7 @@ /** * @licence */ + namespace MyApp\MyNamespace; class AfterClose diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.5.inc b/test/Sniffs/Commenting/DocCommentUnitTest.5.inc index 1b4d23ff..32108414 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.5.inc +++ b/test/Sniffs/Commenting/DocCommentUnitTest.5.inc @@ -2,7 +2,6 @@ /** * @licence */ - namespace MyApp\MyNamespace; class CommentIndent diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.php b/test/Sniffs/Commenting/DocCommentUnitTest.php index 2ab78478..db7b4907 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.php +++ b/test/Sniffs/Commenting/DocCommentUnitTest.php @@ -50,13 +50,13 @@ public function getErrorList($testFile = '') case 'DocCommentUnitTest.5.inc': return [ 3 => 1, - 4 => 1, - 10 => 1, - 12 => 1, + 4 => 2, + 9 => 1, + 11 => 1, + 14 => 1, 15 => 1, 16 => 1, - 17 => 1, - 20 => 1, + 19 => 1, ]; case 'DocCommentUnitTest.6.inc': return [ From 66c607f7e15fe103ea77f84709c5dd899d7f3e21 Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Jun 2017 15:03:25 +0200 Subject: [PATCH 075/225] CS fixes --- src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php | 1 + .../Sniffs/Namespaces/UnusedUseStatementSniff.php | 1 + src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php | 1 + 3 files changed, 3 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php index 55ca4496..c839ae71 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php @@ -3,6 +3,7 @@ * Copied from SlevomatCodingStandard\Sniffs\Arrays\TrailingArrayCommaSniff * with fix: comma shouldn't be added after "[" for empty arrays "[]". */ + namespace ZendCodingStandard\Sniffs\Arrays; use PHP_CodeSniffer\Files\File; diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index 589969b9..d2aec661 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -9,6 +9,7 @@ * * @todo remove once merged to squizlabs/PHP_CodeSniffer (?) */ + namespace ZendCodingStandard\Sniffs\Namespaces; use PHP_CodeSniffer\Files\File; diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index ae99baf8..ed6929c3 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -12,6 +12,7 @@ * [22, 3432, 23, 4], * ] */ + namespace ZendCodingStandard\Sniffs\WhiteSpace; use PHP_CodeSniffer\Files\File; From d02036d73ed7e2b1b6df0124819e8e40d283df3d Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Jun 2017 15:10:45 +0200 Subject: [PATCH 076/225] Only one blank link allowed after file PHPDoc --- .../Sniffs/Commenting/DocCommentSniff.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index 205d5ab9..d183e0f2 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -260,14 +260,14 @@ private function checkAfterClose(File $phpcsFile, $commentStart, $commentEnd) $phpcsFile->fixer->addNewline($newLine); $phpcsFile->fixer->endChangeset(); } - } elseif ($tokens[$prev]['code'] === T_OPEN_TAG - && $tokens[$next]['line'] === $tokens[$commentEnd]['line'] + 1 - ) { - $error = 'Missing blank line after file doc comment.'; - $fix = $phpcsFile->addFixableError($error, $commentEnd, 'MissingBlankLineAfter'); + } elseif ($tokens[$prev]['code'] === T_OPEN_TAG) { + if ($tokens[$next]['line'] === $tokens[$commentEnd]['line'] + 1) { + $error = 'Missing blank line after file doc comment.'; + $fix = $phpcsFile->addFixableError($error, $commentEnd, 'MissingBlankLineAfter'); - if ($fix) { - $phpcsFile->fixer->addNewline($commentEnd); + if ($fix) { + $phpcsFile->fixer->addNewline($commentEnd); + } } } elseif ($tokens[$next]['line'] > $tokens[$commentEnd]['line'] + 1 && ! in_array($tokens[$next]['code'], $allowEmptyLineBefore, true) From dfbdfb93fd9fb3904646459854a54be228525c2d Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 8 Jun 2017 12:10:44 +0100 Subject: [PATCH 077/225] Added sniff NoNullValues Assign null value for class properties is redundant. This sniff checks that null values is not set for all class properties. --- .../Sniffs/Classes/NoNullValuesSniff.php | 63 +++++++++++++++++++ test/Sniffs/Classes/NoNullValuesUnitTest.inc | 24 +++++++ .../Classes/NoNullValuesUnitTest.inc.fixed | 23 +++++++ test/Sniffs/Classes/NoNullValuesUnitTest.php | 25 ++++++++ 4 files changed, 135 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php create mode 100644 test/Sniffs/Classes/NoNullValuesUnitTest.inc create mode 100644 test/Sniffs/Classes/NoNullValuesUnitTest.inc.fixed create mode 100644 test/Sniffs/Classes/NoNullValuesUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php b/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php new file mode 100644 index 00000000..194a4462 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php @@ -0,0 +1,63 @@ +getTokens(); + $token = $tokens[$stackPtr]; + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); + if ($tokens[$next]['code'] !== T_EQUAL) { + return; + } + + $value = $phpcsFile->findNext(Tokens::$emptyTokens, $next + 1, null, true); + if ($tokens[$value]['code'] === T_NULL) { + $error = 'Default null value for the property is redundant.'; + $fix = $phpcsFile->addFixableError($error, $value, 'NullValue'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $stackPtr + 1; $i <= $value; ++$i) { + if (! in_array($tokens[$i]['code'], [T_WHITESPACE, T_EQUAL, T_NULL], true)) { + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->endChangeset(); + } + } + } + + /** + * @inheritDoc + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + $stop = 1; + } + + /** + * @inheritDoc + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + $stop = 1; + } +} diff --git a/test/Sniffs/Classes/NoNullValuesUnitTest.inc b/test/Sniffs/Classes/NoNullValuesUnitTest.inc new file mode 100644 index 00000000..8e850a53 --- /dev/null +++ b/test/Sniffs/Classes/NoNullValuesUnitTest.inc @@ -0,0 +1,24 @@ + 1, + 7 => 1, + 9 => 1, + 11 => 1, + // @todo: Member vars of nested class are not processed correctly + // @see https://github.com/squizlabs/PHP_CodeSniffer/pull/1498 + // 21 => 1, + ]; + } + + public function getWarningList() + { + return []; + } +} From 1cd1dc6664c16b75048ba0e769dc5bb687be7a14 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 21 Jun 2017 19:01:53 +0200 Subject: [PATCH 078/225] Updated to PHP_CodeSniffer 3.0.1 Also updated to the latest version of PHPUnit. --- composer.json | 4 ++-- composer.lock | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/composer.json b/composer.json index e03198ca..e801eebc 100644 --- a/composer.json +++ b/composer.json @@ -7,10 +7,10 @@ "coding standard" ], "require": { - "squizlabs/php_codesniffer": "3.0.0" + "squizlabs/php_codesniffer": "3.0.1" }, "require-dev": { - "phpunit/phpunit": "^6.2.1 || ^5.7.20" + "phpunit/phpunit": "^6.2.2 || ^5.7.20" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 0153e399..ba8d1b80 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "b754e64a4a10f0056246ad4207c082ce", + "content-hash": "43689fb0f5f9c3fd5f5d35801f93357b", "packages": [ { "name": "squizlabs/php_codesniffer", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "b95ff2c3b122a3ee4b57d149a57d2afce65522c3" + "reference": "f9eaf037edf22fdfccf04cb0ab57ebcb1e166219" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/b95ff2c3b122a3ee4b57d149a57d2afce65522c3", - "reference": "b95ff2c3b122a3ee4b57d149a57d2afce65522c3", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/f9eaf037edf22fdfccf04cb0ab57ebcb1e166219", + "reference": "f9eaf037edf22fdfccf04cb0ab57ebcb1e166219", "shasum": "" }, "require": { @@ -55,7 +55,7 @@ "phpcs", "standards" ], - "time": "2017-05-04T00:33:04+00:00" + "time": "2017-06-14T01:23:49+00:00" } ], "packages-dev": [ @@ -1269,16 +1269,16 @@ }, { "name": "symfony/yaml", - "version": "v3.3.0", + "version": "v3.3.2", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "885db865f6b2b918404a1fae28f9ac640f71f994" + "reference": "9752a30000a8ca9f4b34b5227d15d0101b96b063" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/885db865f6b2b918404a1fae28f9ac640f71f994", - "reference": "885db865f6b2b918404a1fae28f9ac640f71f994", + "url": "https://api.github.com/repos/symfony/yaml/zipball/9752a30000a8ca9f4b34b5227d15d0101b96b063", + "reference": "9752a30000a8ca9f4b34b5227d15d0101b96b063", "shasum": "" }, "require": { @@ -1320,7 +1320,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-05-28T10:56:20+00:00" + "time": "2017-06-02T22:05:06+00:00" }, { "name": "webmozart/assert", From 0882b7b7f8b7f959997b4679a27a379b88a41407 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 21 Jun 2017 19:02:16 +0200 Subject: [PATCH 079/225] Removed redundant comparision to `true` --- src/ZendCodingStandard/CodingStandard.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ZendCodingStandard/CodingStandard.php b/src/ZendCodingStandard/CodingStandard.php index ff4eba7e..668cf492 100644 --- a/src/ZendCodingStandard/CodingStandard.php +++ b/src/ZendCodingStandard/CodingStandard.php @@ -51,12 +51,12 @@ public static function suggestType($varType) $pattern = '/^array\(\s*([^\s^=^>]*)(\s*=>\s*(.*))?\s*\)/i'; if (preg_match($pattern, $varType, $matches) !== 0) { $type1 = ''; - if (isset($matches[1]) === true) { + if (isset($matches[1])) { $type1 = $matches[1]; } $type2 = ''; - if (isset($matches[3]) === true) { + if (isset($matches[3])) { $type2 = $matches[3]; } From bacdfda6805866406f22b8a128b870357926f4d8 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 21 Jun 2017 19:02:53 +0200 Subject: [PATCH 080/225] Return type improvements + tests --- src/ZendCodingStandard/CodingStandard.php | 4 ++- .../Commenting/FunctionCommentUnitTest.inc | 32 +++++++++++++++++++ .../FunctionCommentUnitTest.inc.fixed | 32 +++++++++++++++++++ .../Commenting/FunctionCommentUnitTest.php | 4 +++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/CodingStandard.php b/src/ZendCodingStandard/CodingStandard.php index 668cf492..e262c770 100644 --- a/src/ZendCodingStandard/CodingStandard.php +++ b/src/ZendCodingStandard/CodingStandard.php @@ -66,7 +66,9 @@ public static function suggestType($varType) $type2 = ' => ' . $type2; } - return sprintf('array(%s%s)', $type1, $type2); + if ($type1 || $type2) { + return sprintf('array(%s%s)', $type1, $type2); + } } return 'array'; diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc index 1dbafafb..04b3537c 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc @@ -21,4 +21,36 @@ class Foo extends Bar protected function test2() { } + + /** + * @return array(integer => boolean) + */ + private function returnsIntBoolArray() + { + return [1 => true]; + } + + /** + * @return integer[] + */ + private function returnsIntArray() + { + return [0, 1]; + } + + /** + * @return boolean[] + */ + private function returnsBoolArray() + { + return [true, false]; + } + + /** + * @return array() + */ + private function returnsArray() + { + return []; + } } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed index 99e7aab5..f1c72b6e 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed @@ -21,4 +21,36 @@ class Foo extends Bar protected function test2() { } + + /** + * @return array(int => bool) + */ + private function returnsIntBoolArray() + { + return [1 => true]; + } + + /** + * @return int[] + */ + private function returnsIntArray() + { + return [0, 1]; + } + + /** + * @return bool[] + */ + private function returnsBoolArray() + { + return [true, false]; + } + + /** + * @return array + */ + private function returnsArray() + { + return []; + } } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.php b/test/Sniffs/Commenting/FunctionCommentUnitTest.php index f9dfce27..90eb6e24 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.php +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.php @@ -26,6 +26,10 @@ public function getErrorList($testFile = '') return [ 10 => 1, 16 => 1, + 26 => 1, + 34 => 1, + 42 => 1, + 50 => 1, ]; } From 11854ffacc9b41392fcbb7b46b3bc72e6a7b81c1 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 21 Jun 2017 19:03:35 +0200 Subject: [PATCH 081/225] Removed unused variables --- .../Sniffs/Classes/NoNullValuesSniff.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php b/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php index 194a4462..fef76f3f 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php @@ -13,7 +13,6 @@ class NoNullValuesSniff extends AbstractVariableSniff protected function processMemberVar(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); - $token = $tokens[$stackPtr]; $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); if ($tokens[$next]['code'] !== T_EQUAL) { @@ -44,10 +43,7 @@ protected function processMemberVar(File $phpcsFile, $stackPtr) */ protected function processVariable(File $phpcsFile, $stackPtr) { - $tokens = $phpcsFile->getTokens(); - $token = $tokens[$stackPtr]; - - $stop = 1; + // Normal variables are not processed in this sniff. } /** @@ -55,9 +51,6 @@ protected function processVariable(File $phpcsFile, $stackPtr) */ protected function processVariableInString(File $phpcsFile, $stackPtr) { - $tokens = $phpcsFile->getTokens(); - $token = $tokens[$stackPtr]; - - $stop = 1; + // Variables in string are not processed in this sniff. } } From 70b42facc1250e1d6644d9105536c4a866dc8e14 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 21 Jun 2017 19:04:10 +0200 Subject: [PATCH 082/225] Methods\LineAfter sniff supports also anonymous classes --- .../Sniffs/Methods/LineAfterSniff.php | 2 +- test/Sniffs/Methods/LineAfterUnitTest.3.inc | 22 ++++++++++++++++ .../Methods/LineAfterUnitTest.3.inc.fixed | 25 +++++++++++++++++++ test/Sniffs/Methods/LineAfterUnitTest.php | 9 +++++++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 test/Sniffs/Methods/LineAfterUnitTest.3.inc create mode 100644 test/Sniffs/Methods/LineAfterUnitTest.3.inc.fixed diff --git a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php index b8c30213..dde06c2f 100644 --- a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php +++ b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php @@ -11,7 +11,7 @@ class LineAfterSniff extends AbstractScopeSniff */ public function __construct() { - parent::__construct([T_CLASS, T_INTERFACE, T_TRAIT], [T_FUNCTION]); + parent::__construct([T_CLASS, T_INTERFACE, T_TRAIT, T_ANON_CLASS], [T_FUNCTION]); } /** diff --git a/test/Sniffs/Methods/LineAfterUnitTest.3.inc b/test/Sniffs/Methods/LineAfterUnitTest.3.inc new file mode 100644 index 00000000..d247be0e --- /dev/null +++ b/test/Sniffs/Methods/LineAfterUnitTest.3.inc @@ -0,0 +1,22 @@ + 1, 24 => 1, ]; + case 'LineAfterUnitTest.3.inc': + return [ + 6 => 1, + 9 => 1, + 14 => 1, + 19 => 1, + 20 => 2, + 21 => 1, + ]; } return [ From e79d16bbbedc1f3f2f91343233f46861f14c6986 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 21 Jun 2017 19:05:37 +0200 Subject: [PATCH 083/225] Added more test to increase sniffs coverage --- test/Sniffs/Classes/NoNullValuesUnitTest.inc | 4 ++++ test/Sniffs/Classes/NoNullValuesUnitTest.inc.fixed | 4 ++++ test/Sniffs/Classes/NoNullValuesUnitTest.php | 3 ++- test/Sniffs/Formatting/ReferenceUnitTest.inc | 1 + test/Sniffs/Formatting/ReferenceUnitTest.inc.fixed | 1 + .../Formatting/UnnecessaryParenthesesUnitTest.inc | 5 +++++ .../UnnecessaryParenthesesUnitTest.inc.fixed | 5 +++++ .../Formatting/UnnecessaryParenthesesUnitTest.php | 4 ++++ .../Namespaces/ConstAndFunctionKeywordsUnitTest.inc | 10 ++++++++++ .../ConstAndFunctionKeywordsUnitTest.inc.fixed | 10 ++++++++++ .../LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc | 3 +++ ...gicalOperatorNotAtTheEndOfTheLineUnitTest.inc.fixed | 3 +++ .../LogicalOperatorNotAtTheEndOfTheLineUnitTest.php | 1 + 13 files changed, 53 insertions(+), 1 deletion(-) diff --git a/test/Sniffs/Classes/NoNullValuesUnitTest.inc b/test/Sniffs/Classes/NoNullValuesUnitTest.inc index 8e850a53..daa6ef9f 100644 --- a/test/Sniffs/Classes/NoNullValuesUnitTest.inc +++ b/test/Sniffs/Classes/NoNullValuesUnitTest.inc @@ -10,6 +10,8 @@ class NoNullValues public static $v4 =null; + public $v5 = /* comment */ null; + /** * @param mixed $x */ @@ -20,5 +22,7 @@ class NoNullValues $class = new class() { private $s1 = null; }; + + $string = "String $var = null"; } } diff --git a/test/Sniffs/Classes/NoNullValuesUnitTest.inc.fixed b/test/Sniffs/Classes/NoNullValuesUnitTest.inc.fixed index a8547161..b4aa4525 100644 --- a/test/Sniffs/Classes/NoNullValuesUnitTest.inc.fixed +++ b/test/Sniffs/Classes/NoNullValuesUnitTest.inc.fixed @@ -9,6 +9,8 @@ class NoNullValues public static $v4; + public $v5/* comment */; + /** * @param mixed $x */ @@ -19,5 +21,7 @@ class NoNullValues $class = new class() { private $s1 = null; }; + + $string = "String $var = null"; } } diff --git a/test/Sniffs/Classes/NoNullValuesUnitTest.php b/test/Sniffs/Classes/NoNullValuesUnitTest.php index e5b18971..e390b919 100644 --- a/test/Sniffs/Classes/NoNullValuesUnitTest.php +++ b/test/Sniffs/Classes/NoNullValuesUnitTest.php @@ -12,9 +12,10 @@ public function getErrorList() 7 => 1, 9 => 1, 11 => 1, + 13 => 1, // @todo: Member vars of nested class are not processed correctly // @see https://github.com/squizlabs/PHP_CodeSniffer/pull/1498 - // 21 => 1, + // 23 => 1, ]; } diff --git a/test/Sniffs/Formatting/ReferenceUnitTest.inc b/test/Sniffs/Formatting/ReferenceUnitTest.inc index 75a9d2b2..dd5bfd87 100644 --- a/test/Sniffs/Formatting/ReferenceUnitTest.inc +++ b/test/Sniffs/Formatting/ReferenceUnitTest.inc @@ -11,4 +11,5 @@ function (& $var) { } function ($x, & $y) { + $z = $x & $y; } diff --git a/test/Sniffs/Formatting/ReferenceUnitTest.inc.fixed b/test/Sniffs/Formatting/ReferenceUnitTest.inc.fixed index babc382a..eea23f87 100644 --- a/test/Sniffs/Formatting/ReferenceUnitTest.inc.fixed +++ b/test/Sniffs/Formatting/ReferenceUnitTest.inc.fixed @@ -11,4 +11,5 @@ function (&$var) { } function ($x, &$y) { + $z = $x & $y; } diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc index cebad8f4..34941f13 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc @@ -145,5 +145,10 @@ class UnnecessaryParentheses if (($a || $z = strpos($b, $c)) === false) { $z = clone($a); } + + $x = (int) ($a++); + $y = ! ($z instanceof DateTime); + $z = 'string ' . (--$a); + $w = 7 !== (++$b); } } diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed index 28fe32c7..778d4077 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed @@ -145,5 +145,10 @@ class UnnecessaryParentheses if (($a || $z = strpos($b, $c)) === false) { $z = clone $a; } + + $x = (int) $a++; + $y = ! $z instanceof DateTime; + $z = 'string ' . --$a; + $w = 7 !== ++$b; } } diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php index 309b2d18..f72b45bf 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php @@ -45,6 +45,10 @@ public function getErrorList($testFile = '') 138 => 1, 140 => 1, 146 => 1, + 149 => 1, + 150 => 1, + 151 => 1, + 152 => 1, ]; } diff --git a/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.inc b/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.inc index bf2be382..581d05f7 100644 --- a/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.inc +++ b/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.inc @@ -5,3 +5,13 @@ use Function array_merge as am; use ZendCodingStandard\CodingStandard; use CONST E_ERROR as EE; use funcTION\array_diff as ad; + +class MyClass { + use MyTrait; + + public function method() { + $c = new class() { + use AnotherTrait; + }; + } +} diff --git a/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.inc.fixed b/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.inc.fixed index faa6ce39..11cd916f 100644 --- a/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.inc.fixed +++ b/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.inc.fixed @@ -5,3 +5,13 @@ use function array_merge as am; use ZendCodingStandard\CodingStandard; use const E_ERROR as EE; use function \array_diff as ad; + +class MyClass { + use MyTrait; + + public function method() { + $c = new class() { + use AnotherTrait; + }; + } +} diff --git a/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc b/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc index 58530676..9df23d51 100644 --- a/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc +++ b/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc @@ -23,3 +23,6 @@ if (1 && ( 0 || 1 ) ) {} + +if (1 /* comment */ && +2) {} diff --git a/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc.fixed b/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc.fixed index 6fb136b3..67f91399 100644 --- a/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc.fixed +++ b/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc.fixed @@ -23,3 +23,6 @@ if (1 && ( 0 || 1 ) ) {} + +if (1 /* comment */ +&& 2) {} diff --git a/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.php b/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.php index c1777b88..35337072 100644 --- a/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.php +++ b/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.php @@ -15,6 +15,7 @@ public function getErrorList($testFile = '') 15 => 1, 16 => 1, 19 => 1, + 27 => 1, ]; } From ae163a6e38064dd0da146c24a05ef124855edf81 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 21 Jun 2017 19:37:54 +0200 Subject: [PATCH 084/225] Added missing error codes --- .../Sniffs/Arrays/FormatSniff.php | 32 ++++++++----------- .../Sniffs/Arrays/TrailingArrayCommaSniff.php | 7 ++-- .../AlphabeticallySortedTraitsSniff.php | 2 +- .../Sniffs/Classes/TraitUsageSniff.php | 10 +++--- .../Sniffs/Commenting/DocCommentSniff.php | 30 ++++++++--------- .../Sniffs/Formatting/DoubleColonSniff.php | 4 +-- .../Sniffs/Formatting/NewKeywordSniff.php | 4 +-- .../Sniffs/Methods/LineAfterSniff.php | 3 +- .../AlphabeticallySortedUsesSniff.php | 2 +- .../Namespaces/UnusedUseStatementSniff.php | 5 +-- .../UseDoesNotStartWithBackslashSniff.php | 2 +- ...gicalOperatorNotAtTheEndOfTheLineSniff.php | 3 +- .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 2 +- .../PHP/InstantiatingParenthesisSniff.php | 2 +- .../Sniffs/PHP/RedundantSemicolonSniff.php | 6 ++-- .../Strings/NoConcatenationAtTheEndSniff.php | 2 +- .../Sniffs/WhiteSpace/BlankLineSniff.php | 3 +- .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 3 +- .../WhiteSpace/NoBlankLineAtStartSniff.php | 5 +-- 19 files changed, 62 insertions(+), 65 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index 96e67b6f..8064c736 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -56,7 +56,7 @@ private function multiLineArray(File $phpcsFile, $stackPtr) $firstContent = $phpcsFile->findNext(T_WHITESPACE, $bracketOpener + 1, null, true); if ($tokens[$firstContent]['code'] === T_CLOSE_SHORT_ARRAY) { $error = 'Empty array must be in one line.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'EmptyArrayInOneLine'); if ($fix) { $phpcsFile->fixer->replaceToken($bracketOpener + 1, ''); @@ -68,7 +68,7 @@ private function multiLineArray(File $phpcsFile, $stackPtr) $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $bracketCloser - 1, null, true); if ($tokens[$bracketCloser]['line'] > $tokens[$lastContent]['line'] + 1) { $error = 'Blank line found at the end of array'; - $fix = $phpcsFile->addFixableError($error, $bracketCloser - 1, ''); + $fix = $phpcsFile->addFixableError($error, $bracketCloser - 1, 'BlankLineAtTheEnd'); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -93,7 +93,7 @@ private function multiLineArray(File $phpcsFile, $stackPtr) if ($previousLine === $tokens[$next]['line']) { if ($tokens[$next]['code'] !== T_COMMENT) { $error = 'There must be one array element per line.'; - $fix = $phpcsFile->addFixableError($error, $next, ''); + $fix = $phpcsFile->addFixableError($error, $next, 'OneElementPerLine'); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -111,7 +111,8 @@ private function multiLineArray(File $phpcsFile, $stackPtr) ) { $firstOnLine = $phpcsFile->findFirstOnLine([], $next, true); - $fix = $phpcsFile->addFixableError('Empty line is not allowed here.', $firstOnLine - 1, ''); + $error = 'Blank line is not allowed here.'; + $fix = $phpcsFile->addFixableError($error, $firstOnLine - 1, 'BlankLine'); if ($fix) { $phpcsFile->fixer->replaceToken($firstOnLine - 1, ''); @@ -137,7 +138,8 @@ private function multiLineArray(File $phpcsFile, $stackPtr) } } else { $error = 'Invalid array element indent - expected %d spaces; 0 found'; - $fix = $phpcsFile->addFixableError($error, $next, 'ElementIndent', [$expected]); + $data = [$expected]; + $fix = $phpcsFile->addFixableError($error, $next, 'ElementIndent', $data); if ($fix) { $phpcsFile->fixer->addContentBefore($next, str_repeat(' ', $expected)); @@ -164,7 +166,7 @@ private function multiLineArray(File $phpcsFile, $stackPtr) if ($first = $phpcsFile->findFirstOnLine([], $bracketCloser, true)) { if ($first < $bracketCloser - 1) { $error = 'Array closing bracket should be in new line.'; - $fix = $phpcsFile->addFixableError($error, $bracketCloser, ''); + $fix = $phpcsFile->addFixableError($error, $bracketCloser, 'ClosingBracketInNewLine'); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -204,12 +206,9 @@ private function singleLineArray(File $phpcsFile, $stackPtr) // Single-line array - spaces before first element if ($tokens[$bracketOpener + 1]['code'] === T_WHITESPACE) { - $error = sprintf( - 'Expected 0 spaces after array bracket opener; %d found', - strlen($tokens[$bracketOpener + 1]['content']) - ); - - $fix = $phpcsFile->addFixableError($error, $bracketOpener + 1, ''); + $error = 'Expected 0 spaces after array bracket opener; %d found'; + $data = [strlen($tokens[$bracketOpener + 1]['content'])]; + $fix = $phpcsFile->addFixableError($error, $bracketOpener + 1, 'SingleLineSpaceBefore', $data); if ($fix) { $phpcsFile->fixer->replaceToken($bracketOpener + 1, ''); @@ -218,12 +217,9 @@ private function singleLineArray(File $phpcsFile, $stackPtr) // Single-line array - spaces before last element if ($tokens[$bracketCloser - 1]['code'] === T_WHITESPACE) { - $error = sprintf( - 'Expected 0 spaces before array bracket closer; %d found', - strlen($tokens[$bracketCloser - 1]['content']) - ); - - $fix = $phpcsFile->addFixableError($error, $bracketCloser - 1, ''); + $error = 'Expected 0 spaces before array bracket closer; %d found'; + $data = [strlen($tokens[$bracketCloser - 1]['content'])]; + $fix = $phpcsFile->addFixableError($error, $bracketCloser - 1, 'SingleLineSpaceAfter', $data); if ($fix) { $phpcsFile->fixer->replaceToken($bracketCloser - 1, ''); diff --git a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php index c839ae71..a187be9d 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php @@ -57,11 +57,8 @@ public function process(File $phpcsFile, $stackPtr) && $previousToCloseParenthesisToken['code'] !== T_OPEN_SHORT_ARRAY && $closeParenthesisToken['line'] !== $previousToCloseParenthesisToken['line'] ) { - $fix = $phpcsFile->addFixableError( - 'Multiline arrays must have a trailing comma after the last element', - $previousToCloseParenthesisPointer, - '' - ); + $error = 'Multiline arrays must have a trailing comma after the last element'; + $fix = $phpcsFile->addFixableError($error, $previousToCloseParenthesisPointer, 'TrailingComma'); if ($fix) { $phpcsFile->fixer->addContent($previousToCloseParenthesisPointer, ','); diff --git a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php index 9403aadc..73060032 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php @@ -34,7 +34,7 @@ public function process(File $phpcsFile, $stackPtr) if ($order < 0) { $error = 'Traits are incorrectly ordered. The first wrong one is %s'; $data = [$use['name']]; - $fix = $phpcsFile->addFixableError($error, $use['ptrUse'], '', $data); + $fix = $phpcsFile->addFixableError($error, $use['ptrUse'], 'IncorrectOrder', $data); if ($fix) { $this->fixAlphabeticalOrder($phpcsFile, $uses); diff --git a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php index 3383e228..64ced53a 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php @@ -31,7 +31,7 @@ public function process(File $phpcsFile, $stackPtr) $prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$prev]['line'] + 1 !== $tokens[$stackPtr]['line']) { $error = 'Blank line is not allowed before trait declaration'; - $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'BlankLineBeforeTraits'); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -66,7 +66,7 @@ public function process(File $phpcsFile, $stackPtr) $comma = $phpcsFile->findNext(T_COMMA, $stackPtr + 1, $scopeOpener - 1); if ($comma) { $error = 'There must be one USE per declaration.'; - $fix = $phpcsFile->addFixableError($error, $comma, ''); + $fix = $phpcsFile->addFixableError($error, $comma, 'OneUsePerDeclaration'); if ($fix) { $phpcsFile->fixer->replaceToken($comma, ';' . $phpcsFile->eolChar . 'use '); @@ -96,7 +96,7 @@ public function process(File $phpcsFile, $stackPtr) if ($emptyInName) { $error = 'Empty token %s is not allowed in trait name.'; $data = [$tokens[$emptyInName]['type']]; - $fix = $phpcsFile->addFixableError($error, $emptyInName, '', $data); + $fix = $phpcsFile->addFixableError($error, $emptyInName, 'EmptyToken', $data); if ($fix) { $phpcsFile->fixer->replaceToken($emptyInName, ''); @@ -139,7 +139,7 @@ public function process(File $phpcsFile, $stackPtr) $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $scopeOpener + 1, null, true); if ($tokens[$nextNonEmpty]['line'] !== $tokens[$scopeOpener]['line'] + 1) { $error = 'Content must be in next line after opening curly bracket.'; - $fix = $phpcsFile->addFixableError($error, $scopeOpener, ''); + $fix = $phpcsFile->addFixableError($error, $scopeOpener, 'OpeningCurlyBracket'); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -160,7 +160,7 @@ public function process(File $phpcsFile, $stackPtr) ); if ($tokens[$prevNonEmpty]['line'] + 1 !== $tokens[$scopeCloser]['line']) { $error = 'Close curly bracket must be in next line after content.'; - $fix = $phpcsFile->addFixableError($error, $scopeCloser, ''); + $fix = $phpcsFile->addFixableError($error, $scopeCloser, 'ClosingCurlyBracket'); if ($fix) { $phpcsFile->fixer->beginChangeset(); diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index d183e0f2..880f78f0 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -127,7 +127,7 @@ private function checkBeforeOpen(File $phpcsFile, $commentStart) $previous = $phpcsFile->findPrevious(T_WHITESPACE, $commentStart - 1, null, true); if ($tokens[$previous]['line'] === $tokens[$commentStart]['line']) { $error = 'The open comment tag must be the only content on the line.'; - $fix = $phpcsFile->addFixableError($error, $commentStart, ''); + $fix = $phpcsFile->addFixableError($error, $commentStart, 'ContentBeforeOpeningTag'); if ($fix) { $nonEmpty = $phpcsFile->findPrevious(T_WHITESPACE, $commentStart - 1, null, true); @@ -145,7 +145,7 @@ private function checkBeforeOpen(File $phpcsFile, $commentStart) && $tokens[$previous]['code'] !== T_OPEN_CURLY_BRACKET ) { $error = 'Missing blank line before doc comment.'; - $fix = $phpcsFile->addFixableError($error, $commentStart, ''); + $fix = $phpcsFile->addFixableError($error, $commentStart, 'MissingBlankLine'); if ($fix) { $phpcsFile->fixer->addNewlineBefore($commentStart); @@ -167,7 +167,7 @@ private function checkAfterOpen(File $phpcsFile, $commentStart) $next = $phpcsFile->findNext(T_DOC_COMMENT_WHITESPACE, $commentStart + 1, null, true); if ($tokens[$next]['line'] === $tokens[$commentStart]['line']) { $error = 'The open comment tag must be the only content on the line.'; - $fix = $phpcsFile->addFixableError($error, $commentStart, ''); + $fix = $phpcsFile->addFixableError($error, $commentStart, 'ContentAfterOpeningTag'); if ($fix) { $indentToken = $tokens[$commentStart - 1]; @@ -206,7 +206,7 @@ private function checkBeforeClose(File $phpcsFile, $commentEnd) $previous = $phpcsFile->findPrevious(T_DOC_COMMENT_WHITESPACE, $commentEnd - 1, null, true); if ($tokens[$previous]['line'] === $tokens[$commentEnd]['line']) { $error = 'The close comment tag must be the only content on the line.'; - $fix = $phpcsFile->addFixableError($error, $commentEnd, ''); + $fix = $phpcsFile->addFixableError($error, $commentEnd, 'ContentBeforeClosingTag'); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -242,7 +242,7 @@ private function checkAfterClose(File $phpcsFile, $commentStart, $commentEnd) if (! $next) { $error = 'Doc comment is not allowed at the end of the file.'; - $phpcsFile->addError($error, $commentStart, ''); + $phpcsFile->addError($error, $commentStart, 'DocCommentAtTheEndOfTheFile'); return; } @@ -307,7 +307,7 @@ private function checkSpacesInOneLineComment(File $phpcsFile, $commentStart, $co && $tokens[$commentStart + 1]['content'] !== ' ' ) { $error = 'Expected 1 space after opening tag of one line doc block comment.'; - $fix = $phpcsFile->addFixableError($error, $commentStart + 1, ''); + $fix = $phpcsFile->addFixableError($error, $commentStart + 1, 'InvalidSpacing'); if ($fix) { $phpcsFile->fixer->replaceToken($commentStart + 1, ' '); @@ -316,7 +316,7 @@ private function checkSpacesInOneLineComment(File $phpcsFile, $commentStart, $co // This case is currently not supported. // Comment /**@var null $name; */ is not recognized as doc-block comment. $error = 'Expected 1 space after opening tag of one line doc block comment.'; - $fix = $phpcsFile->addFixableError($error, $commentStart, ''); + $fix = $phpcsFile->addFixableError($error, $commentStart, 'InvalidSpacing'); if ($fix) { $phpcsFile->fixer->addContent($commentStart, ' '); @@ -327,7 +327,7 @@ private function checkSpacesInOneLineComment(File $phpcsFile, $commentStart, $co $content = $tokens[$commentEnd - 1]['content']; if (trim($content) . ' ' !== $content) { $error = 'Expected 1 space before closing tag of one line doc block comment.'; - $fix = $phpcsFile->addFixableError($error, $commentEnd - 1, ''); + $fix = $phpcsFile->addFixableError($error, $commentEnd - 1, 'InvalidSpacing'); if ($fix) { $phpcsFile->fixer->replaceToken($commentEnd - 1, trim($content) . ' '); @@ -360,7 +360,7 @@ private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEn ) { if ($tokens[$next + 1]['code'] !== T_DOC_COMMENT_WHITESPACE) { $error = 'There must be exactly one space between star and comment.'; - $fix = $phpcsFile->addFixableError($error, $next, ''); + $fix = $phpcsFile->addFixableError($error, $next, 'NoSpaceAfterStar'); if ($fix) { $phpcsFile->fixer->addContent($next, ' '); @@ -370,7 +370,7 @@ private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEn || $tokens[$next + 1]['line'] === $tokens[$commentStart]['line'] + 1) ) { $error = 'There must be exactly one space between star and comment.'; - $fix = $phpcsFile->addFixableError($error, $next + 1, ''); + $fix = $phpcsFile->addFixableError($error, $next + 1, 'TooManySpacesAfterStar'); if ($fix) { $phpcsFile->fixer->replaceToken($next + 1, ' '); @@ -446,7 +446,7 @@ private function checkBlankLinesInComment(File $phpcsFile, $commentStart, $comme $i = 0; while ($token = $phpcsFile->findNext(T_DOC_COMMENT_STAR, $from + 1, $next - 2)) { if ($i++ > 0) { - $fix = $phpcsFile->addFixableError($error, $token, ''); + $fix = $phpcsFile->addFixableError($error, $token, 'MultipleBlankLines'); if ($fix) { $firstOnLine = $phpcsFile->findFirstOnLine($empty, $token); @@ -516,7 +516,7 @@ private function checkCommentIndents(File $phpcsFile, $commentStart, $commentEnd $indent, strlen($spaces['content']), ]; - $fix = $phpcsFile->addFixableError($error, $commentStart, '', $data); + $fix = $phpcsFile->addFixableError($error, $commentStart, 'InvalidIndent', $data); if ($fix) { $phpcsFile->fixer->replaceToken($commentStart - 1, str_repeat(' ', $indent)); @@ -530,7 +530,7 @@ private function checkCommentIndents(File $phpcsFile, $commentStart, $commentEnd $indent, 0, ]; - $fix = $phpcsFile->addFixableError($error, $commentStart, '', $data); + $fix = $phpcsFile->addFixableError($error, $commentStart, 'InvalidIndent', $data); if ($fix) { $phpcsFile->fixer->replaceToken( @@ -559,7 +559,7 @@ private function checkCommentIndents(File $phpcsFile, $commentStart, $commentEnd $indent + 1, 0, ]; - $fix = $phpcsFile->addFixableError($error, $next, '', $data); + $fix = $phpcsFile->addFixableError($error, $next, 'InvalidIndent', $data); if ($fix) { $phpcsFile->fixer->replaceToken($next - 1, $phpcsFile->eolChar . ' '); @@ -572,7 +572,7 @@ private function checkCommentIndents(File $phpcsFile, $commentStart, $commentEnd $indent + 1, strlen($spaces['content']), ]; - $fix = $phpcsFile->addFixableError($error, $next, '', $data); + $fix = $phpcsFile->addFixableError($error, $next, 'InvalidIndent', $data); if ($fix) { $phpcsFile->fixer->replaceToken($next - 1, str_repeat(' ', $indent + 1)); diff --git a/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php index 6c654120..37d69bb2 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php @@ -23,7 +23,7 @@ public function process(File $phpcsFile, $stackPtr) if ($tokens[$stackPtr - 1]['code'] === T_WHITESPACE) { $error = 'A double colon must not be preceded by a whitespace.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBefore'); if ($fix) { $phpcsFile->fixer->replaceToken($stackPtr - 1, ''); @@ -32,7 +32,7 @@ public function process(File $phpcsFile, $stackPtr) if ($tokens[$stackPtr + 1]['code'] === T_WHITESPACE) { $error = 'A double colon must not be followed by a whitespace.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfter'); if ($fix) { $phpcsFile->fixer->replaceToken($stackPtr + 1, ''); diff --git a/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php index 9cd9440d..543cd789 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php @@ -23,14 +23,14 @@ public function process(File $phpcsFile, $stackPtr) if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) { $error = 'A "new" keyword must be followed by a single space.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MissingSpace'); if ($fix) { $phpcsFile->fixer->addContent($stackPtr, ' '); } } elseif ($tokens[$stackPtr + 1]['content'] !== ' ') { $error = 'A "new" keyword must be followed by a single space.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'TooManySpaces'); if ($fix) { $phpcsFile->fixer->replaceToken($stackPtr + 1, ' '); diff --git a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php index dde06c2f..335f0053 100644 --- a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php +++ b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php @@ -35,7 +35,8 @@ protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScop ) { $error = 'Expected 1 blank line after method; %d found'; $found = max($tokens[$contentAfter]['line'] - $tokens[$closer]['line'] - 1, 0); - $fix = $phpcsFile->addFixableError($error, $closer, '', [$found]); + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $closer, 'BlankLinesAfter', $data); if ($fix) { if ($found) { diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php index b5eda85c..47a90406 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -35,7 +35,7 @@ public function process(File $phpcsFile, $stackPtr) $error = 'Use statements are incorrectly ordered. The first wrong one is %s'; $data = [$use['name']]; - $fix = $phpcsFile->addFixableError($error, $use['ptrUse'], '', $data); + $fix = $phpcsFile->addFixableError($error, $use['ptrUse'], 'IncorrectOrder', $data); if ($fix) { $this->fixAlphabeticalOrder($phpcsFile, $uses); diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index d2aec661..797dbed0 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -160,8 +160,9 @@ public function process(File $phpcsFile, $stackPtr) $classUsed = $phpcsFile->findNext([T_STRING, T_DOC_COMMENT_STRING, T_DOC_COMMENT_TAG], $classUsed + 1); } - $warning = sprintf('Unused use statement "%s"', $className); - $fix = $phpcsFile->addFixableWarning($warning, $stackPtr, 'UnusedUse'); + $warning = 'Unused use statement "%s"'; + $data = [$className]; + $fix = $phpcsFile->addFixableWarning($warning, $stackPtr, 'UnusedUse', $data); if ($fix) { // Remove the whole use statement line. diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php index e2c33bb2..2271bdc9 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php @@ -48,7 +48,7 @@ public function process(File $phpcsFile, $stackPtr) && $tokens[$classPtr]['content'] === '\\') ) { $error = 'Use statement cannot start with a backslash'; - $fix = $phpcsFile->addFixableError($error, $classPtr, ''); + $fix = $phpcsFile->addFixableError($error, $classPtr, 'BackslashAtStart'); if ($fix) { if ($tokens[$classPtr - 1]['code'] !== T_WHITESPACE) { diff --git a/src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php b/src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php index 05db4b19..4ef2170e 100644 --- a/src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php +++ b/src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php @@ -38,7 +38,8 @@ public function process(File $phpcsFile, $stackPtr) if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line'] && $tokens[$next]['line'] !== $tokens[$stackPtr]['line'] ) { - $fix = $phpcsFile->addFixableError('Logical operator cannot be at the end of the line.', $stackPtr, ''); + $error = 'Logical operator cannot be at the end of the line.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'OperatorAtTheEnd'); if ($fix) { $phpcsFile->fixer->beginChangeset(); diff --git a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index d6717b93..0de9f001 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -260,7 +260,7 @@ private function error(File $phpcsFile, $start, $end, $expected, $actual) $expected, $actual, ]; - $fix = $phpcsFile->addFixableError($error, $start + 1, '', $data); + $fix = $phpcsFile->addFixableError($error, $start + 1, 'Invalid', $data); if ($fix) { $phpcsFile->fixer->beginChangeset(); diff --git a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php index 50f8f33d..6a62439e 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php @@ -45,7 +45,7 @@ public function process(File $phpcsFile, $stackPtr) ); $error = 'Missing parenthesis on instantiating a new class.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MissingParenthesis'); if ($fix) { $phpcsFile->fixer->addContent($last, '()'); diff --git a/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php b/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php index 8554f6d1..6b611c9b 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php @@ -40,10 +40,8 @@ public function process(File $phpcsFile, $stackPtr) if ($tokens[$nextNonEmpty]['code'] === T_SEMICOLON) { $error = 'Redundant semicolon after control structure "%s".'; - $data = [ - strtolower($tokens[$scopeCondition]['content']), - ]; - $fix = $phpcsFile->addFixableError($error, $nextNonEmpty, '', $data); + $data = [strtolower($tokens[$scopeCondition]['content'])]; + $fix = $phpcsFile->addFixableError($error, $nextNonEmpty, 'SemicolonFound', $data); if ($fix) { $phpcsFile->fixer->replaceToken($nextNonEmpty, ''); diff --git a/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php b/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php index efa6681d..ba3ee71c 100644 --- a/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php +++ b/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php @@ -28,7 +28,7 @@ public function process(File $phpcsFile, $stackPtr) } $error = 'String concatenation character is not allowed at the end of the line.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr, ''); + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ConcatenationAtTheEnd'); if ($fix) { $phpcsFile->fixer->beginChangeset(); diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php index accfa2b6..317f2bc5 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php @@ -27,7 +27,8 @@ public function process(File $phpcsFile, $stackPtr) $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($next && $tokens[$stackPtr]['line'] < $tokens[$next]['line'] - 2) { - $fix = $phpcsFile->addFixableError('Unexpected blank line found.', $stackPtr + 1, ''); + $error = 'Unexpected blank line found.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr + 1, 'BlankLine'); if ($fix) { $phpcsFile->fixer->replaceToken($stackPtr + 1, ''); diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index ed6929c3..c24c04b0 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -40,7 +40,8 @@ public function process(File $phpcsFile, $stackPtr) $prevToken = $tokens[$stackPtr - 1]; if ($prevToken['code'] === T_WHITESPACE) { $error = 'Expected 0 spaces before comma; found %d'; - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeComma', [strlen($prevToken['content'])]); + $data = [strlen($prevToken['content'])]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeComma', $data); if ($fix) { $phpcsFile->fixer->replaceToken($stackPtr - 1, ''); } diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php index 96ed37f8..2051e8a2 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php @@ -37,8 +37,9 @@ public function process(File $phpcsFile, $stackPtr) $firstContent = $phpcsFile->findNext(T_WHITESPACE, $scopeOpener + 1, null, true); if ($tokens[$firstContent]['line'] > $tokens[$scopeOpener]['line'] + 1) { - $error = sprintf('Blank line found at start of %s', $token['content']); - $fix = $phpcsFile->addFixableError($error, $scopeOpener + 1, ''); + $error = 'Blank line found at start of %s'; + $data = [$token['content']]; + $fix = $phpcsFile->addFixableError($error, $scopeOpener + 1, 'BlankLine', $data); if ($fix) { $phpcsFile->fixer->beginChangeset(); From 364db0dd928331e0ee1075b8f30f5c8af599fb77 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 22 Jun 2017 16:18:07 +0200 Subject: [PATCH 085/225] Unused use sniff checks return types (PHP 7) --- .../Namespaces/UnusedUseStatementSniff.php | 19 +++++++++++++++---- .../Namespaces/UnusedUseStatementUnitTest.inc | 15 +++++++++++++++ .../UnusedUseStatementUnitTest.inc.fixed | 15 +++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index 797dbed0..2abd6839 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -6,6 +6,7 @@ * @see https://github.com/squizlabs/PHP_CodeSniffer/pull/1106 * * - added checks in annotations + * - added checks in return type (PHP 7.0+) * * @todo remove once merged to squizlabs/PHP_CodeSniffer (?) */ @@ -19,6 +20,16 @@ class UnusedUseStatementSniff implements Sniff { + /** + * @var array + */ + private $checkInTokens = [ + T_STRING, + T_RETURN_TYPE, + T_DOC_COMMENT_STRING, + T_DOC_COMMENT_TAG, + ]; + /** * @inheritDoc */ @@ -56,7 +67,7 @@ public function process(File $phpcsFile, $stackPtr) // Search where the class name is used. PHP treats class names case // insensitive, that's why we cannot search for the exact class name string // and need to iterate over all T_STRING tokens in the file. - $classUsed = $phpcsFile->findNext([T_STRING, T_DOC_COMMENT_STRING, T_DOC_COMMENT_TAG], $classPtr + 1); + $classUsed = $phpcsFile->findNext($this->checkInTokens, $classPtr + 1); $className = $tokens[$classPtr]['content']; $lowerClassName = strtolower($className); @@ -109,7 +120,7 @@ public function process(File $phpcsFile, $stackPtr) unset($emptyTokens[T_DOC_COMMENT_TAG]); while ($classUsed !== false) { - if (($tokens[$classUsed]['code'] === T_STRING + if ((in_array($tokens[$classUsed]['code'], [T_STRING, T_RETURN_TYPE], true) && strtolower($tokens[$classUsed]['content']) === $lowerClassName) || ($tokens[$classUsed]['code'] === T_DOC_COMMENT_STRING && preg_match( @@ -129,7 +140,7 @@ public function process(File $phpcsFile, $stackPtr) true ); - if ($tokens[$classUsed]['code'] === T_STRING) { + if (in_array($tokens[$classUsed]['code'], [T_STRING, T_RETURN_TYPE], true)) { // If a backslash is used before the class name then this is some other // use statement. if ($tokens[$beforeUsage]['code'] !== T_USE @@ -157,7 +168,7 @@ public function process(File $phpcsFile, $stackPtr) } } - $classUsed = $phpcsFile->findNext([T_STRING, T_DOC_COMMENT_STRING, T_DOC_COMMENT_TAG], $classUsed + 1); + $classUsed = $phpcsFile->findNext($this->checkInTokens, $classUsed + 1); } $warning = 'Unused use statement "%s"'; diff --git a/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc b/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc index 0814c6d4..ae0f4082 100644 --- a/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc +++ b/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc @@ -24,6 +24,9 @@ use Used11; use FooBar\Used12 as AliasUsed12; use FooBar\Used13; use Unused6, Unused7; +use Used14; +use FooBar\Used15; +use Used16 as AliasUsed16; /** * @Used10 @@ -72,4 +75,16 @@ class Foo /** @var Used13\MyType $x */ $x = $y; } + + protected function test6() : Used14 + { + } + + protected function test7() : Used15\MyClass + { + } + + protected function test8() : AliasUsed16 + { + } } diff --git a/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc.fixed b/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc.fixed index be992c36..1f15dfb0 100644 --- a/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc.fixed +++ b/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc.fixed @@ -18,6 +18,9 @@ use Used11; use FooBar\Used12 as AliasUsed12; use FooBar\Used13; use Unused6, Unused7; +use Used14; +use FooBar\Used15; +use Used16 as AliasUsed16; /** * @Used10 @@ -66,4 +69,16 @@ class Foo /** @var Used13\MyType $x */ $x = $y; } + + protected function test6() : Used14 + { + } + + protected function test7() : Used15\MyClass + { + } + + protected function test8() : AliasUsed16 + { + } } From 19f5daf66ba60f63c9032f7190358bad718fd38f Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 22 Jun 2017 16:18:25 +0200 Subject: [PATCH 086/225] Change to single token instead of arrays of token in "find" calls --- .../Sniffs/Namespaces/UnusedUseStatementSniff.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index 2abd6839..092f81d2 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -73,7 +73,7 @@ public function process(File $phpcsFile, $stackPtr) // Check if the referenced class is in the same namespace as the current // file. If it is then the use statement is not necessary. - $namespacePtr = $phpcsFile->findPrevious([T_NAMESPACE], $stackPtr); + $namespacePtr = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr); // Check if the use statement does aliasing with the "as" keyword. Aliasing // is allowed even in the same namespace. @@ -93,7 +93,7 @@ public function process(File $phpcsFile, $stackPtr) ); $namespace = trim($phpcsFile->getTokensAsString($namespacePtr + 1, $nsEnd - $namespacePtr - 1)); - $useNamespacePtr = $phpcsFile->findNext([T_STRING], $stackPtr + 1); + $useNamespacePtr = $phpcsFile->findNext(T_STRING, $stackPtr + 1); $useNamespaceEnd = $phpcsFile->findNext( [ T_NS_SEPARATOR, From 16451936fc3352e6341d4ee18f7bb93233071430 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 22 Jun 2017 16:22:05 +0200 Subject: [PATCH 087/225] Removed old "todo" --- src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index 0de9f001..325718e6 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -105,8 +105,6 @@ private function checkNew(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); - // todo: check next character after new - should be exactly one space - $nextToken = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); // When "new static", "new self" or "new $var", skip. From c99480e197e2588d76e79b0387cbc2b9c6ab5c51 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 22 Jun 2017 19:56:08 +0200 Subject: [PATCH 088/225] Parentheses are allowed with "list" method --- .../Sniffs/Formatting/UnnecessaryParenthesesSniff.php | 1 + test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc | 2 ++ test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed | 2 ++ 3 files changed, 5 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php index 3f63cf46..dcb98b6e 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -15,6 +15,7 @@ class UnnecessaryParenthesesSniff implements Sniff T_EVAL, T_EXIT, T_ISSET, + T_LIST, T_SELF, T_STATIC, T_STRING, diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc index 34941f13..9760b8aa 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc @@ -150,5 +150,7 @@ class UnnecessaryParentheses $y = ! ($z instanceof DateTime); $z = 'string ' . (--$a); $w = 7 !== (++$b); + + list($var) = explode(',', '1,2,3'); } } diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed index 778d4077..f68955d7 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed @@ -150,5 +150,7 @@ class UnnecessaryParentheses $y = ! $z instanceof DateTime; $z = 'string ' . --$a; $w = 7 !== ++$b; + + list($var) = explode(',', '1,2,3'); } } From 8366b44e5531576b47148a40d47aa624849c4a8c Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 22 Jun 2017 19:59:49 +0200 Subject: [PATCH 089/225] CorrectClassNameCase sniff improvements Checks params type hints (functions and closures), return types (PHP 7.0) and PHPDocs tags (`@var`, `@param`, `@return`, `@throws`) --- .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 147 +++++++++++++++++- .../PHP/CorrectClassNameCaseUnitTest.inc | 30 ++++ .../CorrectClassNameCaseUnitTest.inc.fixed | 30 ++++ .../PHP/CorrectClassNameCaseUnitTest.php | 12 ++ 4 files changed, 217 insertions(+), 2 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index 325718e6..77d60819 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -3,12 +3,11 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; /** * TODO: Better results for this sniff we will have if the parsed class is imported. * We can "include" the file on process, but probably it is not the best solution. - * - * TODO: Checks T_STRING (classes in doc comments?) */ class CorrectClassNameCaseSniff implements Sniff { @@ -37,6 +36,13 @@ public function register() T_DOUBLE_COLON, T_IMPLEMENTS, T_EXTENDS, + // params of function/closures + T_FUNCTION, + T_CLOSURE, + // return type (PHP 7) + T_RETURN_TYPE, + // PHPDocs tags + T_DOC_COMMENT_TAG, ]; } @@ -57,6 +63,16 @@ public function process(File $phpcsFile, $stackPtr) case T_USE: $this->checkUse($phpcsFile, $stackPtr); return; + case T_FUNCTION: + case T_CLOSURE: + $this->checkFunctionParams($phpcsFile, $stackPtr); + return; + case T_RETURN_TYPE: + $this->checkReturnType($phpcsFile, $stackPtr); + return; + case T_DOC_COMMENT_TAG: + $this->checkTag($phpcsFile, $stackPtr); + return; } $this->checkExtendsAndImplements($phpcsFile, $stackPtr); @@ -161,6 +177,133 @@ private function checkUse(File $phpcsFile, $stackPtr) $this->checkClass($phpcsFile, $nextToken, $end); } + /** + * Checks params type hints + * + * @param File $phpcsFile + * @param int $stackPtr + * @return void + */ + private function checkFunctionParams(File $phpcsFile, $stackPtr) + { + $params = $phpcsFile->getMethodParameters($stackPtr); + + foreach ($params as $param) { + if (! $param['type_hint']) { + continue; + } + + $end = $phpcsFile->findPrevious(Tokens::$emptyTokens, $param['token'] - 1, null, true); + $before = $phpcsFile->findPrevious([T_COMMA, T_OPEN_PARENTHESIS, T_WHITESPACE], $end - 1); + $first = $phpcsFile->findNext(Tokens::$emptyTokens, $before + 1, null, true); + + $this->checkClass($phpcsFile, $first, $end + 1); + } + } + + /** + * Checks return type (PHP 7) + * + * @param File $phpcsFile + * @param int $stackPtr + * @return void + */ + private function checkReturnType(File $phpcsFile, $stackPtr) + { + $before = $phpcsFile->findPrevious([T_COLON, T_NULLABLE], $stackPtr - 1); + $first = $phpcsFile->findNext(Tokens::$emptyTokens, $before + 1, null, true); + + $this->checkClass($phpcsFile, $first, $stackPtr + 1); + } + + /** + * Checks PHPDocs tags + * + * @param File $phpcsFile + * @param int $stackPtr + * @return void + */ + private function checkTag(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (! in_array($tokens[$stackPtr]['content'], ['@var', '@param', '@return', '@throws'], true) + || $tokens[$stackPtr + 1]['code'] !== T_DOC_COMMENT_WHITESPACE + || $tokens[$stackPtr + 2]['code'] !== T_DOC_COMMENT_STRING + ) { + return; + } + + $string = $tokens[$stackPtr + 2]['content']; + list($types) = explode(' ', $string); + $typesArr = explode('|', $types); + + $newTypesArr = []; + foreach ($typesArr as $type) { + $expected = $this->getExcepctedName($phpcsFile, $type, $stackPtr + 2); + + $newTypesArr[] = $expected; + } + + $newTypes = implode('|', $newTypesArr); + + if ($newTypes !== $types) { + $error = 'Invalid class name case: expected %s; found %s'; + $data = [ + $newTypes, + $types, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr + 2, 'InvalidInPhpDocs', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken( + $stackPtr + 2, + preg_replace('/^' . preg_quote($types) . '/', $newTypes, $string) + ); + } + } + } + + /** + * Returns expected class name for given $class. + * + * @param File $phpcsFile + * @param string $class + * @param int $stackPtr + * @return string + */ + private function getExcepctedName(File $phpcsFile, $class, $stackPtr) + { + if ($class[0] === '\\') { + $result = $this->hasDifferentCase(ltrim($class, '\\')); + if ($result) { + return '\\' . $result; + } + + return $class; + } + + $imports = $this->getGlobalUses($phpcsFile); + + // Check if class is imported. + if (isset($imports[strtolower($class)])) { + if ($imports[strtolower($class)]['alias'] !== $class) { + return $imports[strtolower($class)]['alias']; + } + } else { + // Class from the same namespace. + $namespace = $this->getNamespace($phpcsFile, $stackPtr); + $fullClassName = ltrim($namespace . '\\' . $class, '\\'); + + $result = $this->hasDifferentCase(ltrim($fullClassName, '\\')); + if ($result) { + return ltrim(substr($result, strlen($namespace)), '\\'); + } + } + + return $class; + } + /** * Checks "extends" and "implements" classes/interfaces. * diff --git a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc index 104008c7..988ad229 100644 --- a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc +++ b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc @@ -54,4 +54,34 @@ class MyClass return new CorrectclassnamecaseUnitTest(); } + + public function method2( + datetime $a, + correctclassnamecaseunittest $b + ) : datEtimE { + /** + * @param Arrayobject $ao + * @return \arrayiterator + */ + $f = function(arrayobject $ao) : \arrayiterator { + }; + } + + /** + * @see https://zendframework.com/ + * @param int $a + * @param array|\TraverSable|\ArRAyObJeCt $b + * @param callable $c + * @param testCase|CorrectclassnamecaseUnitTest|null $testCase + * @return \zendcodingstandardtest\sniffs\testcase + * @throws \Rangeexception + */ + public function method3( + int $a, + $b, + callable $c, + testcase $testCase = null + ) : \zendcodingstandardtest\sniffs\testcase { + throw new \RangeException; + } } diff --git a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc.fixed b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc.fixed index b2dd7455..258c69b1 100644 --- a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc.fixed +++ b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc.fixed @@ -54,4 +54,34 @@ class MyClass return new CorrectClassNameCaseUnitTest(); } + + public function method2( + DateTime $a, + CorrectClassNameCaseUnitTest $b + ) : DateTime { + /** + * @param ArrayObject $ao + * @return \ArrayIterator + */ + $f = function(ArrayObject $ao) : \ArrayIterator { + }; + } + + /** + * @see https://zendframework.com/ + * @param int $a + * @param array|\Traversable|\ArrayObject $b + * @param callable $c + * @param TestCase|CorrectClassNameCaseUnitTest|null $testCase + * @return \ZendCodingStandardTest\Sniffs\TestCase + * @throws \RangeException + */ + public function method3( + int $a, + $b, + callable $c, + TestCase $testCase = null + ) : \ZendCodingStandardTest\Sniffs\TestCase { + throw new \RangeException; + } } diff --git a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php index 5bedb50a..7aa28ebe 100644 --- a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php +++ b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php @@ -38,6 +38,18 @@ public function getErrorList($testFile = '') 43 => 1, 48 => 1, 55 => 1, + 59 => 1, + 60 => 1, + 61 => 1, + // 63 => 0, + 64 => 1, + 66 => 2, + 73 => 1, + 75 => 1, + 76 => 1, + 77 => 1, + 83 => 1, + 84 => 1, ]; } From 7651f640a1f9327e32dc227238368e0ef4a84d1d Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 22 Jun 2017 20:27:40 +0200 Subject: [PATCH 090/225] ReturnType sniff - PHP 7 and 7.1 (nullable types) Return type has to be formated as following: ``` function method(): ?array { } ``` So: - no space before colon - single space after colon - no space after nullable op (?), if present --- .../Sniffs/WhiteSpace/ReturnTypeSniff.php | 123 ++++++++++++++++++ test/Sniffs/WhiteSpace/ReturnTypeUnitTest.inc | 82 ++++++++++++ .../WhiteSpace/ReturnTypeUnitTest.inc.fixed | 80 ++++++++++++ test/Sniffs/WhiteSpace/ReturnTypeUnitTest.php | 49 +++++++ 4 files changed, 334 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/WhiteSpace/ReturnTypeSniff.php create mode 100644 test/Sniffs/WhiteSpace/ReturnTypeUnitTest.inc create mode 100644 test/Sniffs/WhiteSpace/ReturnTypeUnitTest.inc.fixed create mode 100644 test/Sniffs/WhiteSpace/ReturnTypeUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ReturnTypeSniff.php new file mode 100644 index 00000000..29b8e0d5 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ReturnTypeSniff.php @@ -0,0 +1,123 @@ +getTokens(); + + $colon = $phpcsFile->findPrevious(T_COLON, $stackPtr - 1); + + // No space before colon. + if ($tokens[$colon - 1]['code'] !== T_CLOSE_PARENTHESIS) { + $error = 'There must be no space before colon.'; + $fix = $phpcsFile->addFixableError($error, $colon - 1, 'SpaceBeforeColon'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $token = $colon - 1; + do { + $phpcsFile->fixer->replaceToken($token, ''); + + --$token; + } while ($tokens[$token]['code'] !== T_CLOSE_PARENTHESIS); + $phpcsFile->fixer->endChangeset(); + } + } + + // Only one space after colon. + if ($tokens[$colon + 1]['code'] !== T_WHITESPACE) { + $error = 'There must be one space after colon and before return type declaration.'; + $fix = $phpcsFile->addFixableError($error, $colon, 'NoSpaceAfterColon'); + + if ($fix) { + $phpcsFile->fixer->addContent($colon, ' '); + } + } elseif ($tokens[$colon + 1]['content'] !== ' ') { + $error = 'There must be only one space after colon and before return type declaration.'; + $fix = $phpcsFile->addFixableError($error, $colon + 1, 'TooManySpacesAfterColon'); + + if ($fix) { + $phpcsFile->fixer->replaceToken($colon + 1, ' '); + } + } + + $nullable = $phpcsFile->findNext(T_NULLABLE, $colon + 1, $stackPtr); + if ($nullable) { + // Check if there is space after nullable operator. + if ($tokens[$nullable + 1]['code'] === T_WHITESPACE) { + $error = 'Space is not not allowed after nullable operator.'; + $fix = $phpcsFile->addFixableError($error, $nullable + 1, 'SpaceAfterNullable'); + + if ($fix) { + $phpcsFile->fixer->replaceToken($nullable + 1, ''); + } + } + } + + $first = $phpcsFile->findNext(Tokens::$emptyTokens, ($nullable ?: $colon) + 1, null, true); + $end = $phpcsFile->findNext([T_SEMICOLON, T_OPEN_CURLY_BRACKET], $stackPtr + 1); + $last = $phpcsFile->findPrevious(Tokens::$emptyTokens, $end - 1, null, true); + + $invalid = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR, T_RETURN_TYPE], $first, $last + 1, true); + if ($invalid) { + $error = 'Return type declaration contains invalid token %s'; + $data = [$tokens[$invalid]['type']]; + $fix = $phpcsFile->addFixableError($error, $invalid, 'InvalidToken', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($invalid, ''); + } + + return; + } + + $returnType = trim($phpcsFile->getTokensAsString($first, $last - $first + 1)); + + if ($first === $last + && in_array(strtolower($returnType), $this->simpleReturnTypes, true) + && ! in_array($returnType, $this->simpleReturnTypes, true) + ) { + $error = 'Simple return type must be lowercase. Found "%s", expected "%s"'; + $data = [ + $returnType, + strtolower($returnType), + ]; + $fix = $phpcsFile->addFixableError($error, $first, 'LowerCaseSimpleType', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($stackPtr, strtolower($returnType)); + } + } + } +} diff --git a/test/Sniffs/WhiteSpace/ReturnTypeUnitTest.inc b/test/Sniffs/WhiteSpace/ReturnTypeUnitTest.inc new file mode 100644 index 00000000..0bdb90fe --- /dev/null +++ b/test/Sniffs/WhiteSpace/ReturnTypeUnitTest.inc @@ -0,0 +1,82 @@ + 1, + 9 => 1, + 27 => 2, + 36 => 1, + 42 => 2, + 50 => 2, + 55 => 2, + 56 => 2, + 57 => 2, + 58 => 3, + 59 => 3, + 60 => 2, + 61 => 1, + 62 => 2, + 63 => 1, + 64 => 2, + 65 => 1, + 66 => 2, + 67 => 1, + 68 => 2, + 69 => 1, + 70 => 2, + 71 => 1, + 72 => 2, + 73 => 1, + 74 => 2, + 75 => 1, + 77 => 2, + 78 => 1, + 80 => 1, + 81 => 3, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 1de64dd56e6fb741517b3ddd6d8c41e18e4098b9 Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 23 Jun 2017 13:08:07 +0200 Subject: [PATCH 091/225] ReturnType sniff moved from WhiteSpace to Formating This sniff check not only white space around colon and nullable op (return type) but also lowercase of simple types, so better place is "formating" than "white-space" --- .../Sniffs/{WhiteSpace => Formatting}/ReturnTypeSniff.php | 5 ++++- .../Sniffs/{WhiteSpace => Formatting}/ReturnTypeUnitTest.inc | 0 .../{WhiteSpace => Formatting}/ReturnTypeUnitTest.inc.fixed | 0 .../Sniffs/{WhiteSpace => Formatting}/ReturnTypeUnitTest.php | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) rename src/ZendCodingStandard/Sniffs/{WhiteSpace => Formatting}/ReturnTypeSniff.php (97%) rename test/Sniffs/{WhiteSpace => Formatting}/ReturnTypeUnitTest.inc (100%) rename test/Sniffs/{WhiteSpace => Formatting}/ReturnTypeUnitTest.inc.fixed (100%) rename test/Sniffs/{WhiteSpace => Formatting}/ReturnTypeUnitTest.php (94%) diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php similarity index 97% rename from src/ZendCodingStandard/Sniffs/WhiteSpace/ReturnTypeSniff.php rename to src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php index 29b8e0d5..3aee0db6 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php @@ -1,5 +1,5 @@ Date: Fri, 23 Jun 2017 17:43:26 +0200 Subject: [PATCH 092/225] AlphabeticalSortedUses fix for single namespace in a file --- .../AlphabeticallySortedUsesSniff.php | 5 ++-- .../AlphabeticallySortedUsesUnitTest.1.inc | 28 +++++++++++++++++++ ...phabeticallySortedUsesUnitTest.1.inc.fixed | 28 +++++++++++++++++++ .../AlphabeticallySortedUsesUnitTest.php | 7 +++++ 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc create mode 100644 test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php index 47a90406..bf583cbc 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -68,8 +68,9 @@ private function getUseStatements(File $phpcsFile, $scopePtr) } while ($use = $phpcsFile->findNext(T_USE, $start + 1, $end)) { if (! CodingStandard::isGlobalUse($phpcsFile, $use) - || ! isset($tokens[$use]['conditions'][$scopePtr]) - || $tokens[$use]['level'] !== $tokens[$scopePtr]['level'] + 1 + || ($end !== null + && (! isset($tokens[$use]['conditions'][$scopePtr]) + || $tokens[$use]['level'] !== $tokens[$scopePtr]['level'] + 1)) ) { $start = $use; continue; diff --git a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc new file mode 100644 index 00000000..99187b7d --- /dev/null +++ b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc @@ -0,0 +1,28 @@ + $foo; + }; + } + + public function anonym() + { + return new class() { + use AnotherTrait; + }; + } +} diff --git a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed new file mode 100644 index 00000000..def7d99f --- /dev/null +++ b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed @@ -0,0 +1,28 @@ + $foo; + }; + } + + public function anonym() + { + return new class() { + use AnotherTrait; + }; + } +} diff --git a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php index 4e0421f6..a6b1b088 100644 --- a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php +++ b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php @@ -7,6 +7,13 @@ class AlphabeticallySortedUsesUnitTest extends TestCase { public function getErrorList($testFile = '') { + switch ($testFile) { + case 'AlphabeticallySortedUsesUnitTest.1.inc': + return [ + 6 => 1, + ]; + } + return [ 5 => 1, 20 => 1, From 31ff8dc11cb43bafee103c07eee8655829233995 Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 23 Jun 2017 18:36:23 +0200 Subject: [PATCH 093/225] Fixed alphabetical sorting of global uses and traits --- .../AlphabeticallySortedTraitsSniff.php | 14 +++++++++++++- .../AlphabeticallySortedUsesSniff.php | 14 +++++++++++++- ...lphabeticallySortedTraitsUnitTest.inc.fixed | 18 +++++++++--------- .../AlphabeticallySortedTraitsUnitTest.php | 2 +- .../AlphabeticallySortedUsesUnitTest.1.inc | 3 +++ ...lphabeticallySortedUsesUnitTest.1.inc.fixed | 3 +++ 6 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php index 73060032..0854ecf3 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php @@ -118,7 +118,19 @@ private function getEndOfTraitScope(File $phpcsFile, $stackPtr) */ private function compareUseStatements(array $a, array $b) { - return strnatcasecmp($a['name'], $b['name']); + return strnatcasecmp( + $this->clearName($a['name']), + $this->clearName($b['name']) + ); + } + + /** + * @param string $name + * @return string + */ + private function clearName($name) + { + return str_replace('\\', ':', $name); } /** diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php index bf583cbc..3a8c454d 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -115,7 +115,10 @@ private function getUseStatements(File $phpcsFile, $scopePtr) private function compareUseStatements(array $a, array $b) { if ($a['type'] === $b['type']) { - return strnatcasecmp($a['name'], $b['name']); + return strnatcasecmp( + $this->clearName($a['name']), + $this->clearName($b['name']) + ); } if ($a['type'] === 'class' @@ -127,6 +130,15 @@ private function compareUseStatements(array $a, array $b) return 1; } + /** + * @param string $name + * @return string + */ + private function clearName($name) + { + return str_replace('\\', ':', $name); + } + /** * @param File $phpcsFile * @param array[] $uses diff --git a/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.inc.fixed b/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.inc.fixed index 962220ff..6d160384 100644 --- a/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.inc.fixed +++ b/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.inc.fixed @@ -6,15 +6,7 @@ use MyProject\HelloWorld; class Foo { - use BazTrait, - \MyTrait; -use Hello { sayHello as private myPrivateHello; } -use HelloWorld - { sayHello as protected;} -use TooManySpaces; -use XTrait , YTrait - ; -use \A, \B { + use \A, \B { \B::smallTalk insteadof \A; \A::bigTalk insteadof \B; } @@ -23,6 +15,14 @@ use \AnotherTrait { } use \BarTrait ; use\Foo\ ATrait; +use BazTrait, + \MyTrait; +use Hello { sayHello as private myPrivateHello; } +use HelloWorld + { sayHello as protected;} +use TooManySpaces; +use XTrait , YTrait + ; /** diff --git a/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.php b/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.php index 91556a58..9ff07965 100644 --- a/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.php +++ b/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.php @@ -8,7 +8,7 @@ class AlphabeticallySortedTraitsUnitTest extends TestCase public function getErrorList() { return [ - 16 => 1, + 12 => 1, 36 => 1, ]; } diff --git a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc index 99187b7d..bd623ae9 100644 --- a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc +++ b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc @@ -8,6 +8,9 @@ use B; use A; use function Y; use function X; +use A\TagManager; +use A\Tag; +use A\Tag\Tags; class J { use MyTrait; diff --git a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed index def7d99f..aa5ccff9 100644 --- a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed +++ b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed @@ -3,6 +3,9 @@ namespace Foo; use A; +use A\Tag; +use A\Tag\Tags; +use A\TagManager; use B; use function X; use function Y; From 5127e4ff81e5be9b66d0e22dc711af739cea84bc Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 23 Jun 2017 20:25:41 +0200 Subject: [PATCH 094/225] MultilineBrace sniff Checks indent of multiline control structures and braces position. --- .../ControlStructures/MultilineBraceSniff.php | 170 ++++++++++++++++++ .../MultilineBraceUnitTest.inc | 73 ++++++++ .../MultilineBraceUnitTest.inc.fixed | 76 ++++++++ .../MultilineBraceUnitTest.php | 32 ++++ 4 files changed, 351 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php create mode 100644 test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc create mode 100644 test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed create mode 100644 test/Sniffs/ControlStructures/MultilineBraceUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php b/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php new file mode 100644 index 00000000..8b75a335 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php @@ -0,0 +1,170 @@ +getTokens(); + + $opener = $tokens[$stackPtr]; + if (! isset($opener['scope_condition'])) { + return; + } + + $scopeCondition = $tokens[$opener['scope_condition']]; + + if ($scopeCondition['line'] === $opener['line']) { + return; + } + + if (in_array($scopeCondition['code'], $this->skipStructures, true)) { + return; + } + + $parenthesis = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); + if ($tokens[$parenthesis]['code'] !== T_CLOSE_PARENTHESIS) { + return; + } + + // Find indent before control structure + $indent = ''; + $firstOnLine = $phpcsFile->findFirstOnLine([], $opener['scope_condition'], true); + if ($tokens[$firstOnLine]['code'] === T_WHITESPACE) { + $indent = $tokens[$firstOnLine]['content']; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $parenthesis - 1, null, true); + if ($scopeCondition['line'] === $tokens[$prev]['line']) { + $error = 'Closing parenthesis must be in the same line as control structure.'; + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'UnnecessaryLineBreak'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $prev + 1; $i < $parenthesis; ++$i) { + if ($tokens[$i]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + $phpcsFile->fixer->endChangeset(); + } + + return; + } + + if ($tokens[$prev]['line'] <= $tokens[$parenthesis]['line'] - 1) { + // Check indent + $whitespace = $phpcsFile->findFirstOnLine(T_WHITESPACE, $parenthesis); + if ($whitespace && $tokens[$whitespace]['content'] !== $indent) { + // Invalid indent before parenthesis + $error = 'Invalid indent before closing parenthesis.'; + $fix = $phpcsFile->addFixableError($error, $whitespace, 'InvalidIndentBeforeParenthesis'); + + if ($fix) { + $phpcsFile->fixer->replaceToken($whitespace, $indent); + } + } elseif (! $whitespace && $indent) { + // Missing indent before closing parenthesis + $error = 'Missing indent before closing parenthesis.'; + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'MissingIndentBeforeParenthesis'); + + if ($fix) { + $phpcsFile->fixer->addContentBefore($parenthesis, $indent); + } + } + } else { + // Needed new line before parenthesis + $error = 'Closing parentheses must be in new line.'; + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'NewLine'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore($parenthesis, $indent); + $phpcsFile->fixer->addNewlineBefore($parenthesis); + $phpcsFile->fixer->endChangeset(); + } + } + + // Check indent of each line + $line = $scopeCondition['line']; + $token = $opener['scope_condition']; + $depth = 0; + do { + while ($tokens[$token]['line'] === $line) { + if ($tokens[$token]['code'] === T_OPEN_PARENTHESIS) { + ++$depth; + } elseif ($tokens[$token]['code'] === T_CLOSE_PARENTHESIS) { + --$depth; + } + + ++$token; + } + $line = $tokens[$token]['line']; + + if ($line >= $opener['line']) { + break; + } + + $first = $phpcsFile->findNext(Tokens::$emptyTokens, $token, null, true); + if ($tokens[$first]['code'] === T_CLOSE_PARENTHESIS) { + $expectedIndentWidth = strlen($indent) + ($depth - 1) * $this->indent; + } else { + $expectedIndentWidth = strlen($indent) + $depth * $this->indent; + } + + if ($tokens[$token]['code'] === T_WHITESPACE) { + $indentWidth = strlen($tokens[$token]['content']); + + if ($indentWidth !== $expectedIndentWidth) { + $error = 'Invalid indent. Expected %d spaces, found %d'; + $data = [ + $expectedIndentWidth, + $indentWidth, + ]; + $fix = $phpcsFile->addFixableError($error, $token, 'InvalidIndent', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($token, str_repeat(' ', $expectedIndentWidth)); + } + } + } else { + // Missing indent + $error = 'Missing line indent. Expected %d spaces, found 0'; + $data = [$expectedIndentWidth]; + $fix = $phpcsFile->addFixableError($error, $token, 'MissingIndent', $data); + + if ($fix) { + $phpcsFile->fixer->addContentBefore($token, str_repeat(' ', $expectedIndentWidth)); + } + } + } while ($line < $opener['line']); + } +} diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc new file mode 100644 index 00000000..d40873b1 --- /dev/null +++ b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc @@ -0,0 +1,73 @@ +getMessage(); +} + +class MyClass +{ +} + +function y($a, $b) { + if ($a + || $b) { + return $a; + } elseif ($a + && $b + ) { + return $b; + } elseif ($a + xor $b +) { + return $a - $b; + } elseif ($a + || $b) { + return $a; + } elseif ($a + && $b) { + return $b; + } + + return $a + $b; +} + +while (1 +|| 2) { + continue; +} + +if ($a +&& ($b +|| $c) +&& preg_match( + '/a/', + 'b' +) +) { + return 12; +} + +$a = 'string'; +$v = $a{0}; +$z = $a->{$v}; diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed new file mode 100644 index 00000000..d50074af --- /dev/null +++ b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed @@ -0,0 +1,76 @@ +getMessage(); +} + +class MyClass +{ +} + +function y($a, $b) { + if ($a + || $b + ) { + return $a; + } elseif ($a + && $b + ) { + return $b; + } elseif ($a + xor $b + ) { + return $a - $b; + } elseif ($a + || $b + ) { + return $a; + } elseif ($a + && $b + ) { + return $b; + } + + return $a + $b; +} + +while (1 + || 2 +) { + continue; +} + +if ($a + && ($b + || $c) + && preg_match( + '/a/', + 'b' + ) +) { + return 12; +} + +$a = 'string'; +$v = $a{0}; +$z = $a->{$v}; diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php new file mode 100644 index 00000000..0e94c3f8 --- /dev/null +++ b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php @@ -0,0 +1,32 @@ + 1, + 34 => 1, + 38 => 1, + 41 => 1, + 42 => 1, + 45 => 1, + 48 => 1, + 56 => 1, + 61 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 5f4c79990cd317affaccd7042df84c7ce7d5e657 Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 23 Jun 2017 20:52:41 +0200 Subject: [PATCH 095/225] Fixed sorting global uses, traits and traits statements Using regular sorting instead of natural --- .../AlphabeticallySortedTraitsSniff.php | 2 +- .../Sniffs/Classes/TraitUsageSniff.php | 30 ++++++++++++++++--- .../AlphabeticallySortedUsesSniff.php | 2 +- .../AlphabeticallySortedUsesUnitTest.1.inc | 2 ++ ...phabeticallySortedUsesUnitTest.1.inc.fixed | 2 ++ 5 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php index 0854ecf3..b758542e 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php @@ -118,7 +118,7 @@ private function getEndOfTraitScope(File $phpcsFile, $stackPtr) */ private function compareUseStatements(array $a, array $b) { - return strnatcasecmp( + return strcasecmp( $this->clearName($a['name']), $this->clearName($b['name']) ); diff --git a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php index 64ced53a..5235fe7b 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php @@ -191,7 +191,7 @@ public function process(File $phpcsFile, $stackPtr) continue; } - $order = strnatcasecmp($statement['content'], $lastStatement['content']); + $order = $this->compareStatements($statement, $lastStatement); if ($order < 0) { $error = 'Statements in trait are incorrectly ordered. The first wrong is %s'; @@ -273,9 +273,7 @@ private function fixAlphabeticalOrder(File $phpcsFile, array $statements) } } - usort($statements, function (array $a, array $b) { - return strnatcasecmp($a['content'], $b['content']); - }); + usort($statements, [$this, 'compareStatements']); $begins = array_column($statements, 'begin'); sort($begins); @@ -286,4 +284,28 @@ private function fixAlphabeticalOrder(File $phpcsFile, array $statements) $phpcsFile->fixer->endChangeset(); } + + /** + * @internal + * + * @param array $a + * @param array $b + * @return int + */ + public function compareStatements(array $a, array $b) + { + return strcasecmp( + $this->clearName($a['content']), + $this->clearName($b['content']) + ); + } + + /** + * @param string $name + * @return string + */ + private function clearName($name) + { + return str_replace('\\', ':', $name); + } } diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php index 3a8c454d..9221eb67 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -115,7 +115,7 @@ private function getUseStatements(File $phpcsFile, $scopePtr) private function compareUseStatements(array $a, array $b) { if ($a['type'] === $b['type']) { - return strnatcasecmp( + return strcasecmp( $this->clearName($a['name']), $this->clearName($b['name']) ); diff --git a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc index bd623ae9..b1f261bb 100644 --- a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc +++ b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc @@ -11,6 +11,8 @@ use function X; use A\TagManager; use A\Tag; use A\Tag\Tags; +use C\Response as MyResponse; +use C\Response\HtmlResponse; class J { use MyTrait; diff --git a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed index aa5ccff9..727cce42 100644 --- a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed +++ b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed @@ -7,6 +7,8 @@ use A\Tag; use A\Tag\Tags; use A\TagManager; use B; +use C\Response as MyResponse; +use C\Response\HtmlResponse; use function X; use function Y; use const C; From 7c379bf83366b4c04285fd99702beaf1f5f24fff Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 23 Jun 2017 21:19:23 +0200 Subject: [PATCH 096/225] UnusedUseStatement sniff fix Fixed detecting unused use statements --- .../Sniffs/Namespaces/UnusedUseStatementSniff.php | 1 + test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc | 7 ++++++- .../Sniffs/Namespaces/UnusedUseStatementUnitTest.inc.fixed | 7 ++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index 092f81d2..c8eabf2b 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -145,6 +145,7 @@ public function process(File $phpcsFile, $stackPtr) // use statement. if ($tokens[$beforeUsage]['code'] !== T_USE && $tokens[$beforeUsage]['code'] !== T_NS_SEPARATOR + && $tokens[$beforeUsage]['code'] !== T_OBJECT_OPERATOR ) { return; } diff --git a/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc b/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc index ae0f4082..295bc00c 100644 --- a/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc +++ b/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc @@ -25,8 +25,9 @@ use FooBar\Used12 as AliasUsed12; use FooBar\Used13; use Unused6, Unused7; use Used14; -use FooBar\Used15; +use Unused5\Used15; use Used16 as AliasUsed16; +use FooBar\Used17; /** * @Used10 @@ -37,6 +38,9 @@ class Foo { use Traits\MyTrait; use Traits\Used1; + use Used17; + + private $unused2; protected function test1(Used1 $x, Used2 $y) { @@ -86,5 +90,6 @@ class Foo protected function test8() : AliasUsed16 { + $this->unused2 = new \Unused1(); } } diff --git a/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc.fixed b/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc.fixed index 1f15dfb0..899b0331 100644 --- a/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc.fixed +++ b/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.inc.fixed @@ -19,8 +19,9 @@ use FooBar\Used12 as AliasUsed12; use FooBar\Used13; use Unused6, Unused7; use Used14; -use FooBar\Used15; +use Unused5\Used15; use Used16 as AliasUsed16; +use FooBar\Used17; /** * @Used10 @@ -31,6 +32,9 @@ class Foo { use Traits\MyTrait; use Traits\Used1; + use Used17; + + private $unused2; protected function test1(Used1 $x, Used2 $y) { @@ -80,5 +84,6 @@ class Foo protected function test8() : AliasUsed16 { + $this->unused2 = new \Unused1(); } } From c86c2a54f2bd462169e511f8d10ae63e8aaa042c Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 26 Jun 2017 11:25:53 +0200 Subject: [PATCH 097/225] UnnecessaryParentheses sniff fix Do not remove parentheses when method called on new instance i.e.: (new DateTime())->modify(...) --- .../Sniffs/Formatting/UnnecessaryParenthesesSniff.php | 6 ++++++ test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc | 2 ++ .../Formatting/UnnecessaryParenthesesUnitTest.inc.fixed | 2 ++ 3 files changed, 10 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php index dcb98b6e..6acddd81 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -75,6 +75,12 @@ public function process(File $phpcsFile, $stackPtr) $closePtr = $tokens[$stackPtr]['parenthesis_closer']; + // Skip when method call on new instance i.e.: (new DateTime())->modify(...) + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $closePtr + 1, null, true); + if ($tokens[$next]['code'] === T_OBJECT_OPERATOR) { + return; + } + $firstInside = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, $closePtr, true); $lastInside = $phpcsFile->findPrevious(Tokens::$emptyTokens, $closePtr - 1, $stackPtr + 1, true); diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc index 9760b8aa..7041ae2f 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc @@ -152,5 +152,7 @@ class UnnecessaryParentheses $w = 7 !== (++$b); list($var) = explode(',', '1,2,3'); + + $date = (new DateTime())->modify('+1 year'); } } diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed index f68955d7..69fca663 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed @@ -152,5 +152,7 @@ class UnnecessaryParentheses $w = 7 !== ++$b; list($var) = explode(',', '1,2,3'); + + $date = (new DateTime())->modify('+1 year'); } } From ab76e6f84c9a875b49c8ab4acfe14845214f72b0 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Jun 2017 22:59:52 +0200 Subject: [PATCH 098/225] Added TernaryOperator sniff Consistent usage of ternary operator, if one part is in new line, then the other should be also in new line. Operator can't be at the end of the line. --- .../Sniffs/Operators/TernaryOperatorSniff.php | 139 ++++++++++++++++++ .../Operators/TernaryOperatorUnitTest.inc | 32 ++++ .../TernaryOperatorUnitTest.inc.fixed | 34 +++++ .../Operators/TernaryOperatorUnitTest.php | 26 ++++ 4 files changed, 231 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php create mode 100644 test/Sniffs/Operators/TernaryOperatorUnitTest.inc create mode 100644 test/Sniffs/Operators/TernaryOperatorUnitTest.inc.fixed create mode 100644 test/Sniffs/Operators/TernaryOperatorUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php b/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php new file mode 100644 index 00000000..773e53e8 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php @@ -0,0 +1,139 @@ +getTokens(); + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); + if ($tokens[$next]['line'] > $tokens[$stackPtr]['line']) { + $error = 'Invalid position of ternary operator "%s"'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Invalid', $data); + + if ($fix) { + $isShortTernary = $tokens[$stackPtr]['code'] === T_INLINE_THEN + && $tokens[$next]['code'] === T_INLINE_ELSE; + + $phpcsFile->fixer->beginChangeset(); + if ($tokens[$stackPtr - 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($stackPtr - 1, ''); + } + $phpcsFile->fixer->replaceToken($stackPtr, ''); + if ($isShortTernary) { + if ($tokens[$stackPtr + 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($stackPtr + 1, ''); + } + $phpcsFile->fixer->addContentBefore($next, $tokens[$stackPtr]['content']); + } else { + $phpcsFile->fixer->addContentBefore($next, $tokens[$stackPtr]['content'] . ' '); + } + $phpcsFile->fixer->endChangeset(); + } + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); + if ($tokens[$prev]['line'] < $tokens[$stackPtr]['line']) { + $isThen = $tokens[$stackPtr]['code'] === T_INLINE_THEN; + + $token = $isThen + ? $this->findElse($phpcsFile, $stackPtr) + : $this->findThen($phpcsFile, $stackPtr); + + if ($token === $prev || $token === $next) { + return; + } + + $tokenNext = $phpcsFile->findNext(Tokens::$emptyTokens, $token + 1, null, true); + $tokenPrev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $token - 1, null, true); + if ($tokens[$tokenNext]['line'] === $tokens[$token]['line'] + && $tokens[$tokenPrev]['line'] === $tokens[$token]['line'] + ) { + $error = 'Invalid position of ternary operator "%s"'; + $data = [$tokens[$token]['content']]; + $fix = $phpcsFile->addFixableError($error, $token, 'Invalid', $data); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + if ($tokens[$token - 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($token - 1, ''); + } + $phpcsFile->fixer->addNewlineBefore($token); + $phpcsFile->fixer->endChangeset(); + } + } + } + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @return int|null + */ + protected function findThen(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $count = 0; + + $i = $stackPtr; + while ($i = $phpcsFile->findPrevious([T_INLINE_ELSE, T_INLINE_THEN], $i - 1)) { + if ($tokens[$i]['code'] === T_INLINE_ELSE) { + ++$count; + } else { + --$count; + + if ($count < 0) { + return $i; + } + } + } + + return null; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @return int|null + */ + protected function findElse(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $count = 0; + + $i = $stackPtr; + while ($i = $phpcsFile->findNext([T_INLINE_ELSE, T_INLINE_THEN], $i + 1)) { + if ($tokens[$i]['code'] === T_INLINE_THEN) { + ++$count; + } else { + --$count; + + if ($count < 0) { + return $i; + } + } + } + + return null; + } +} diff --git a/test/Sniffs/Operators/TernaryOperatorUnitTest.inc b/test/Sniffs/Operators/TernaryOperatorUnitTest.inc new file mode 100644 index 00000000..bec81ff4 --- /dev/null +++ b/test/Sniffs/Operators/TernaryOperatorUnitTest.inc @@ -0,0 +1,32 @@ + 1, + 7 => 1, + 9 => 1, + 12 => 1, + 16 => 1, + 19 => 1, + 24 => 1, + 31 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 79f934eb78237cb62b38e2fa73100217abeccc72 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Jun 2017 23:00:36 +0200 Subject: [PATCH 099/225] Fixes in MultilineBrace sniff --- .../ControlStructures/MultilineBraceSniff.php | 152 ++++++++++++++---- .../MultilineBraceUnitTest.inc | 43 +++++ .../MultilineBraceUnitTest.inc.fixed | 45 +++++- .../MultilineBraceUnitTest.php | 12 +- 4 files changed, 215 insertions(+), 37 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php b/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php index 8b75a335..7f8210f9 100644 --- a/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php +++ b/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php @@ -55,14 +55,12 @@ public function process(File $phpcsFile, $stackPtr) return; } - // Find indent before control structure - $indent = ''; - $firstOnLine = $phpcsFile->findFirstOnLine([], $opener['scope_condition'], true); - if ($tokens[$firstOnLine]['code'] === T_WHITESPACE) { - $indent = $tokens[$firstOnLine]['content']; - } - - $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $parenthesis - 1, null, true); + $prev = $phpcsFile->findPrevious( + Tokens::$emptyTokens + [T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS], + $parenthesis - 1, + null, + true + ); if ($scopeCondition['line'] === $tokens[$prev]['line']) { $error = 'Closing parenthesis must be in the same line as control structure.'; $fix = $phpcsFile->addFixableError($error, $parenthesis, 'UnnecessaryLineBreak'); @@ -80,36 +78,116 @@ public function process(File $phpcsFile, $stackPtr) return; } - if ($tokens[$prev]['line'] <= $tokens[$parenthesis]['line'] - 1) { - // Check indent - $whitespace = $phpcsFile->findFirstOnLine(T_WHITESPACE, $parenthesis); - if ($whitespace && $tokens[$whitespace]['content'] !== $indent) { - // Invalid indent before parenthesis - $error = 'Invalid indent before closing parenthesis.'; - $fix = $phpcsFile->addFixableError($error, $whitespace, 'InvalidIndentBeforeParenthesis'); + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $parenthesis - 1, null, true); + $squashClose = false; + while ($tokens[$prev]['code'] === T_CLOSE_PARENTHESIS + && $tokens[$prev]['line'] > $scopeCondition['line'] + && $tokens[$tokens[$prev]['parenthesis_opener']]['line'] === $scopeCondition['line'] + ) { + $firstOnLine = $phpcsFile->findFirstOnLine( + Tokens::$emptyTokens + [T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS], + $prev, + true + ); + + if ($firstOnLine) { + break; + } + + if ($tokens[$prev]['line'] <= $tokens[$parenthesis]['line'] - 1) { + $error = 'Invalid closing parenthesis position.'; + $fix = $phpcsFile->addFixableError($error, $prev, 'InvalidClosingParenthesisPosition'); if ($fix) { - $phpcsFile->fixer->replaceToken($whitespace, $indent); + $phpcsFile->fixer->beginChangeset(); + for ($i = $prev + 1; $i < $parenthesis; ++$i) { + if ($tokens[$i]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + $phpcsFile->fixer->endChangeset(); } - } elseif (! $whitespace && $indent) { - // Missing indent before closing parenthesis - $error = 'Missing indent before closing parenthesis.'; - $fix = $phpcsFile->addFixableError($error, $parenthesis, 'MissingIndentBeforeParenthesis'); + } elseif ($tokens[$prev + 1]['code'] === T_WHITESPACE) { + $error = 'Unexpected whitespace before closing parenthesis.'; + $fix = $phpcsFile->addFixableError($error, $prev + 1, 'UnexpectedSpacesBeforeClosingParenthesis'); if ($fix) { - $phpcsFile->fixer->addContentBefore($parenthesis, $indent); + $phpcsFile->fixer->replaceToken($prev + 1, ''); + } + } + + $squashClose = true; + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $prev - 1, null, true); + } + + // Find indent before control structure + $indent = ''; + $firstOnLine = $phpcsFile->findFirstOnLine([], $opener['scope_condition'], true); + if ($tokens[$firstOnLine]['code'] === T_WHITESPACE) { + $indent = $tokens[$firstOnLine]['content']; + } + + if ($squashClose) { + $closerParenthesis = $phpcsFile->findFirstOnLine(T_CLOSE_PARENTHESIS, $parenthesis - 1); + $openerParenthesis = $tokens[$closerParenthesis]['parenthesis_opener']; + $beforeOpener = $phpcsFile->findPrevious(Tokens::$emptyTokens, $openerParenthesis - 1, null, true); + + // @todo: check if we have test for both - string and variable + if ($tokens[$beforeOpener]['code'] !== T_STRING + && $tokens[$beforeOpener]['code'] !== T_VARIABLE + ) { + // Move closer parenthesis to line above + $error = 'Invalid position of closing parenthesis'; + $fix = $phpcsFile->addFixableError($error, $closerParenthesis, 'InvalidClosingParenthesisPosition'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $i = $closerParenthesis; + while (--$i) { + if ($tokens[$i]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($i, ''); + if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false) { + break; + } + } + } + $phpcsFile->fixer->addNewline($closerParenthesis); + $phpcsFile->fixer->endChangeset(); } } } else { - // Needed new line before parenthesis - $error = 'Closing parentheses must be in new line.'; - $fix = $phpcsFile->addFixableError($error, $parenthesis, 'NewLine'); + if ($tokens[$prev]['line'] <= $tokens[$parenthesis]['line'] - 1) { + // Check indent + $whitespace = $phpcsFile->findFirstOnLine(T_WHITESPACE, $parenthesis); + if ($whitespace && $tokens[$whitespace]['content'] !== $indent) { + // Invalid indent before parenthesis + $error = 'Invalid indent before closing parenthesis.'; + $fix = $phpcsFile->addFixableError($error, $whitespace, 'InvalidIndentBeforeParenthesis'); - if ($fix) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->addContentBefore($parenthesis, $indent); - $phpcsFile->fixer->addNewlineBefore($parenthesis); - $phpcsFile->fixer->endChangeset(); + if ($fix) { + $phpcsFile->fixer->replaceToken($whitespace, $indent); + } + } elseif (! $whitespace && $indent) { + // Missing indent before closing parenthesis + $error = 'Missing indent before closing parenthesis.'; + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'MissingIndentBeforeParenthesis'); + + if ($fix) { + $phpcsFile->fixer->addContentBefore($parenthesis, $indent); + } + } + } else { + // Needed new line before parenthesis + $error = 'Closing parentheses must be in new line.'; + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'NewLine'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore($parenthesis, $indent); + $phpcsFile->fixer->addNewlineBefore($parenthesis); + $phpcsFile->fixer->endChangeset(); + } } } @@ -120,6 +198,14 @@ public function process(File $phpcsFile, $stackPtr) do { while ($tokens[$token]['line'] === $line) { if ($tokens[$token]['code'] === T_OPEN_PARENTHESIS) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $token - 1, null, true); + if ($tokens[$prev]['code'] === T_STRING + || $tokens[$prev]['code'] === T_VARIABLE + ) { + $token = $tokens[$token]['parenthesis_closer'] + 1; + $line = $tokens[$token]['line']; + continue; + } ++$depth; } elseif ($tokens[$token]['code'] === T_CLOSE_PARENTHESIS) { --$depth; @@ -134,8 +220,12 @@ public function process(File $phpcsFile, $stackPtr) } $first = $phpcsFile->findNext(Tokens::$emptyTokens, $token, null, true); - if ($tokens[$first]['code'] === T_CLOSE_PARENTHESIS) { - $expectedIndentWidth = strlen($indent) + ($depth - 1) * $this->indent; + if (in_array( + $tokens[$first]['code'], + Tokens::$comparisonTokens + [T_INSTANCEOF => T_INSTANCEOF], + true + )) { + $expectedIndentWidth = strlen($indent) + ($depth + 1) * $this->indent; } else { $expectedIndentWidth = strlen($indent) + $depth * $this->indent; } diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc index d40873b1..3cdb8c1a 100644 --- a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc +++ b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc @@ -68,6 +68,49 @@ if ($a return 12; } +if (false === strpos( + 'haystack', + 'needle' +) +) { + echo 0; +} + +if ($a +!== $b + && $c +instanceof \DateTime +) { + echo 1; +} + +if ('x' === trim(sprintf( + 'a %s', + 'b' +) +) +) { + echo 2; +} + +if (true === strpos( + 'a', + 'b' +) ) { + echo 3; +} + +if ($a && ($b || $c +)) { + echo 4; +} + +if ($a && ($b + || $c +)) { + echo 5; +} + $a = 'string'; $v = $a{0}; $z = $a->{$v}; diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed index d50074af..add8b992 100644 --- a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed +++ b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed @@ -64,13 +64,52 @@ if ($a && ($b || $c) && preg_match( - '/a/', - 'b' - ) + '/a/', + 'b' +) ) { return 12; } +if (false === strpos( + 'haystack', + 'needle' +)) { + echo 0; +} + +if ($a + !== $b + && $c + instanceof \DateTime +) { + echo 1; +} + +if ('x' === trim(sprintf( + 'a %s', + 'b' +))) { + echo 2; +} + +if (true === strpos( + 'a', + 'b' +)) { + echo 3; +} + +if ($a && ($b || $c)) { + echo 4; +} + +if ($a && ($b + || $c) +) { + echo 5; +} + $a = 'string'; $v = $a{0}; $z = $a->{$v}; diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php index 0e94c3f8..769474b0 100644 --- a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php +++ b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php @@ -19,9 +19,15 @@ public function getErrorList($testFile = '') 61 => 1, 62 => 1, 63 => 1, - 64 => 1, - 65 => 1, - 66 => 1, + 74 => 1, + 80 => 1, + 82 => 1, + 90 => 1, + 91 => 1, + 99 => 1, + 104 => 1, + 109 => 1, + 110 => 1, ]; } From 4aa2f2cfa1a50291117913b71644cbdbce28f745 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Jun 2017 23:03:03 +0200 Subject: [PATCH 100/225] Renamed sniff LogicalOperatorNotAtTheEndOfTheLine -> BooleanOperator --- ...NotAtTheEndOfTheLineSniff.php => BooleanOperatorSniff.php} | 4 ++-- ...heEndOfTheLineUnitTest.inc => BooleanOperatorUnitTest.inc} | 0 ...neUnitTest.inc.fixed => BooleanOperatorUnitTest.inc.fixed} | 0 ...heEndOfTheLineUnitTest.php => BooleanOperatorUnitTest.php} | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename src/ZendCodingStandard/Sniffs/Operators/{LogicalOperatorNotAtTheEndOfTheLineSniff.php => BooleanOperatorSniff.php} (91%) rename test/Sniffs/Operators/{LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc => BooleanOperatorUnitTest.inc} (100%) rename test/Sniffs/Operators/{LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc.fixed => BooleanOperatorUnitTest.inc.fixed} (100%) rename test/Sniffs/Operators/{LogicalOperatorNotAtTheEndOfTheLineUnitTest.php => BooleanOperatorUnitTest.php} (86%) diff --git a/src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php b/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php similarity index 91% rename from src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php rename to src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php index 4ef2170e..c5cca5b6 100644 --- a/src/ZendCodingStandard/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineSniff.php +++ b/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php @@ -5,14 +5,14 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; -class LogicalOperatorNotAtTheEndOfTheLineSniff implements Sniff +class BooleanOperatorSniff implements Sniff { /** * @inheritDoc */ public function register() { - return [T_BOOLEAN_AND, T_BOOLEAN_OR, T_LOGICAL_AND, T_LOGICAL_OR, T_LOGICAL_XOR]; + return Tokens::$booleanOperators; } /** diff --git a/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc b/test/Sniffs/Operators/BooleanOperatorUnitTest.inc similarity index 100% rename from test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc rename to test/Sniffs/Operators/BooleanOperatorUnitTest.inc diff --git a/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc.fixed b/test/Sniffs/Operators/BooleanOperatorUnitTest.inc.fixed similarity index 100% rename from test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.inc.fixed rename to test/Sniffs/Operators/BooleanOperatorUnitTest.inc.fixed diff --git a/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.php b/test/Sniffs/Operators/BooleanOperatorUnitTest.php similarity index 86% rename from test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.php rename to test/Sniffs/Operators/BooleanOperatorUnitTest.php index 35337072..1c7d4480 100644 --- a/test/Sniffs/Operators/LogicalOperatorNotAtTheEndOfTheLineUnitTest.php +++ b/test/Sniffs/Operators/BooleanOperatorUnitTest.php @@ -3,7 +3,7 @@ use ZendCodingStandardTest\Sniffs\TestCase; -class LogicalOperatorNotAtTheEndOfTheLineUnitTest extends TestCase +class BooleanOperatorUnitTest extends TestCase { public function getErrorList($testFile = '') { From 47af616cbf21c9fb9cbfb46fc41d05ae2cb78941 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Jun 2017 23:07:56 +0200 Subject: [PATCH 101/225] TernaryOperator sniff - nested ternary operator tests --- test/Sniffs/Operators/TernaryOperatorUnitTest.inc | 7 +++++++ test/Sniffs/Operators/TernaryOperatorUnitTest.inc.fixed | 8 ++++++++ test/Sniffs/Operators/TernaryOperatorUnitTest.php | 2 ++ 3 files changed, 17 insertions(+) diff --git a/test/Sniffs/Operators/TernaryOperatorUnitTest.inc b/test/Sniffs/Operators/TernaryOperatorUnitTest.inc index bec81ff4..da96a6bf 100644 --- a/test/Sniffs/Operators/TernaryOperatorUnitTest.inc +++ b/test/Sniffs/Operators/TernaryOperatorUnitTest.inc @@ -30,3 +30,10 @@ $h = $foo $i = $foo ? : $bar; + +$j = $foo + ? $bar ?: $var : $tar; + +$k = $foo ? + $bar ?: $var + : $tar; diff --git a/test/Sniffs/Operators/TernaryOperatorUnitTest.inc.fixed b/test/Sniffs/Operators/TernaryOperatorUnitTest.inc.fixed index 077f9163..c55df908 100644 --- a/test/Sniffs/Operators/TernaryOperatorUnitTest.inc.fixed +++ b/test/Sniffs/Operators/TernaryOperatorUnitTest.inc.fixed @@ -32,3 +32,11 @@ $h = $foo $i = $foo ?: $bar; + +$j = $foo + ? $bar ?: $var +: $tar; + +$k = $foo + ? $bar ?: $var + : $tar; diff --git a/test/Sniffs/Operators/TernaryOperatorUnitTest.php b/test/Sniffs/Operators/TernaryOperatorUnitTest.php index e81cac56..98e7498d 100644 --- a/test/Sniffs/Operators/TernaryOperatorUnitTest.php +++ b/test/Sniffs/Operators/TernaryOperatorUnitTest.php @@ -16,6 +16,8 @@ public function getErrorList($testFile = '') 19 => 1, 24 => 1, 31 => 1, + 35 => 1, + 37 => 1, ]; } From c7c6b6bb9c6de1024dd4e01bad5120ed3c523118 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 29 Jun 2017 10:35:23 +0200 Subject: [PATCH 102/225] MultilineBrace sniff - added test to check variable method calls --- .../ControlStructures/MultilineBraceSniff.php | 1 - .../MultilineBraceUnitTest.inc | 7 +++++++ .../MultilineBraceUnitTest.inc.fixed | 6 ++++++ .../MultilineBraceUnitTest.php | 17 +++++++++-------- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php b/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php index 7f8210f9..3040c7ae 100644 --- a/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php +++ b/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php @@ -133,7 +133,6 @@ public function process(File $phpcsFile, $stackPtr) $openerParenthesis = $tokens[$closerParenthesis]['parenthesis_opener']; $beforeOpener = $phpcsFile->findPrevious(Tokens::$emptyTokens, $openerParenthesis - 1, null, true); - // @todo: check if we have test for both - string and variable if ($tokens[$beforeOpener]['code'] !== T_STRING && $tokens[$beforeOpener]['code'] !== T_VARIABLE ) { diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc index 3cdb8c1a..fe2883ff 100644 --- a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc +++ b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc @@ -76,6 +76,13 @@ if (false === strpos( echo 0; } +if (false === $method( + 'value' +) +) { + echo 1; +} + if ($a !== $b && $c diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed index add8b992..d182e648 100644 --- a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed +++ b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed @@ -78,6 +78,12 @@ if (false === strpos( echo 0; } +if (false === $method( + 'value' +)) { + echo 1; +} + if ($a !== $b && $c diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php index 769474b0..068a4e82 100644 --- a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php +++ b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php @@ -20,14 +20,15 @@ public function getErrorList($testFile = '') 62 => 1, 63 => 1, 74 => 1, - 80 => 1, - 82 => 1, - 90 => 1, - 91 => 1, - 99 => 1, - 104 => 1, - 109 => 1, - 110 => 1, + 81 => 1, + 87 => 1, + 89 => 1, + 97 => 1, + 98 => 1, + 106 => 1, + 111 => 1, + 116 => 1, + 117 => 1, ]; } From cb744144910a9bf4a389ac07fe18253173dddc0f Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 30 Jun 2017 22:14:56 +0200 Subject: [PATCH 103/225] Improvements of MultilineBrace sniff Added more test cases and implemented changes to work with all provided tests --- .../ControlStructures/MultilineBraceSniff.php | 115 +++++++++++------- .../MultilineBraceUnitTest.inc | 29 +++++ .../MultilineBraceUnitTest.inc.fixed | 27 +++- .../MultilineBraceUnitTest.php | 5 + 4 files changed, 131 insertions(+), 45 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php b/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php index 3040c7ae..af89dfe7 100644 --- a/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php +++ b/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php @@ -20,6 +20,16 @@ class MultilineBraceSniff implements Sniff T_CLOSURE, ]; + /** + * @var array + */ + private $functionCall = [ + T_STRING, + T_VARIABLE, + T_CLOSE_CURLY_BRACKET, + T_CLOSE_PARENTHESIS, + ]; + /** * @inheritDoc */ @@ -78,22 +88,68 @@ public function process(File $phpcsFile, $stackPtr) return; } - $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $parenthesis - 1, null, true); + $token = $tokens[$parenthesis]['parenthesis_opener']; + while ($token = $phpcsFile->findNext(T_CLOSE_PARENTHESIS, $token + 1, $parenthesis)) { + $prevCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, $token - 1, null, true); + if ($tokens[$prevCloser]['line'] === $tokens[$token]['line']) { + continue; + } + + $open = $tokens[$token]['parenthesis_opener']; + $prevOpener = $phpcsFile->findPrevious(Tokens::$emptyTokens, $open - 1, null, true); + $first = $phpcsFile->findFirstOnLine([], $open, true); + + if (in_array($tokens[$prevOpener]['code'], $this->functionCall, true)) { + // It is a function call. + if ($tokens[$open]['line'] < $tokens[$token]['line'] + && $tokens[$token - 1]['line'] < $tokens[$token]['line'] + && $tokens[$first]['code'] === T_WHITESPACE + ) { + $expectedIndentWidth = strlen($tokens[$first]['content']); + $error = 'Multi-line function closing parenthesis not indented correctly;' + . ' expected %d spaces but found 0'; + $data = [ + $expectedIndentWidth, + ]; + $fix = $phpcsFile->addFixableError($error, $token, 'ClosingParenthesisMultiLineFunction', $data); + + if ($fix) { + $phpcsFile->fixer->addContentBefore($token, str_repeat(' ', $expectedIndentWidth)); + } + } + } else { + $error = 'Invalid closing parenthesis position.'; + $fix = $phpcsFile->addFixableError($error, $token, 'InvalidClosingParenthesisPosition'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($prevCloser, $tokens[$token]['content']); + $phpcsFile->fixer->replaceToken($token, ''); + $t = $token + 1; + while ($tokens[$t]['code'] === T_WHITESPACE + && $tokens[$t]['line'] === $tokens[$token]['line'] + ) { + $phpcsFile->fixer->replaceToken($t, ''); + + ++$t; + } + $phpcsFile->fixer->endChangeset(); + } + } + } + + $prev = $parenthesis; $squashClose = false; - while ($tokens[$prev]['code'] === T_CLOSE_PARENTHESIS + while (($prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $prev - 1, null, true)) + && $tokens[$prev]['code'] === T_CLOSE_PARENTHESIS && $tokens[$prev]['line'] > $scopeCondition['line'] && $tokens[$tokens[$prev]['parenthesis_opener']]['line'] === $scopeCondition['line'] - ) { - $firstOnLine = $phpcsFile->findFirstOnLine( + && ! $phpcsFile->findFirstOnLine( Tokens::$emptyTokens + [T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS], $prev, true - ); - - if ($firstOnLine) { - break; - } - + ) + ) { if ($tokens[$prev]['line'] <= $tokens[$parenthesis]['line'] - 1) { $error = 'Invalid closing parenthesis position.'; $fix = $phpcsFile->addFixableError($error, $prev, 'InvalidClosingParenthesisPosition'); @@ -117,8 +173,6 @@ public function process(File $phpcsFile, $stackPtr) } $squashClose = true; - - $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $prev - 1, null, true); } // Find indent before control structure @@ -128,34 +182,7 @@ public function process(File $phpcsFile, $stackPtr) $indent = $tokens[$firstOnLine]['content']; } - if ($squashClose) { - $closerParenthesis = $phpcsFile->findFirstOnLine(T_CLOSE_PARENTHESIS, $parenthesis - 1); - $openerParenthesis = $tokens[$closerParenthesis]['parenthesis_opener']; - $beforeOpener = $phpcsFile->findPrevious(Tokens::$emptyTokens, $openerParenthesis - 1, null, true); - - if ($tokens[$beforeOpener]['code'] !== T_STRING - && $tokens[$beforeOpener]['code'] !== T_VARIABLE - ) { - // Move closer parenthesis to line above - $error = 'Invalid position of closing parenthesis'; - $fix = $phpcsFile->addFixableError($error, $closerParenthesis, 'InvalidClosingParenthesisPosition'); - - if ($fix) { - $phpcsFile->fixer->beginChangeset(); - $i = $closerParenthesis; - while (--$i) { - if ($tokens[$i]['code'] === T_WHITESPACE) { - $phpcsFile->fixer->replaceToken($i, ''); - if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false) { - break; - } - } - } - $phpcsFile->fixer->addNewline($closerParenthesis); - $phpcsFile->fixer->endChangeset(); - } - } - } else { + if (! $squashClose) { if ($tokens[$prev]['line'] <= $tokens[$parenthesis]['line'] - 1) { // Check indent $whitespace = $phpcsFile->findFirstOnLine(T_WHITESPACE, $parenthesis); @@ -198,9 +225,7 @@ public function process(File $phpcsFile, $stackPtr) while ($tokens[$token]['line'] === $line) { if ($tokens[$token]['code'] === T_OPEN_PARENTHESIS) { $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $token - 1, null, true); - if ($tokens[$prev]['code'] === T_STRING - || $tokens[$prev]['code'] === T_VARIABLE - ) { + if (in_array($tokens[$prev]['code'], $this->functionCall, true)) { $token = $tokens[$token]['parenthesis_closer'] + 1; $line = $tokens[$token]['line']; continue; @@ -219,7 +244,9 @@ public function process(File $phpcsFile, $stackPtr) } $first = $phpcsFile->findNext(Tokens::$emptyTokens, $token, null, true); - if (in_array( + if ($tokens[$first]['code'] === T_CLOSE_PARENTHESIS) { + continue; + } elseif (in_array( $tokens[$first]['code'], Tokens::$comparisonTokens + [T_INSTANCEOF => T_INSTANCEOF], true diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc index fe2883ff..7b9eb166 100644 --- a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc +++ b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc @@ -121,3 +121,32 @@ if ($a && ($b $a = 'string'; $v = $a{0}; $z = $a->{$v}; + +if ($a + && ($b + || $c + ) +) { + echo 1; +} + +if ($a + && ($b + || $c + ) && ($d + || $e + ) +) { + echo 2; +} + +if ($a + && ($b + || $c + ) + && ($d + || $e + ) +) { + echo 3; +} diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed index d182e648..e09367f1 100644 --- a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed +++ b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed @@ -66,7 +66,7 @@ if ($a && preg_match( '/a/', 'b' -) + ) ) { return 12; } @@ -119,3 +119,28 @@ if ($a && ($b $a = 'string'; $v = $a{0}; $z = $a->{$v}; + +if ($a + && ($b + || $c) +) { + echo 1; +} + +if ($a + && ($b + || $c) + && ($d + || $e) +) { + echo 2; +} + +if ($a + && ($b + || $c) + && ($d + || $e) +) { + echo 3; +} diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php index 068a4e82..040d23d6 100644 --- a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php +++ b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php @@ -29,6 +29,11 @@ public function getErrorList($testFile = '') 111 => 1, 116 => 1, 117 => 1, + 128 => 1, + 136 => 1, + 138 => 1, + 146 => 1, + 149 => 1, ]; } From 618ee11656a3cad46bd66cfc93fbbec45119fc78 Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 30 Jun 2017 22:26:42 +0200 Subject: [PATCH 104/225] Updated travis configuration - added slack notifications - removed irc notifications - added legacy dependencies (PHPUnit 5 on PHP 5.6) - added build on PHP 7.2 (nightly) - removed hhvm build - set colun=120 for composer show output --- .travis.yml | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 176c1a22..e5d5ff1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ env: global: - COMPOSER_ARGS="--no-interaction" - COVERAGE_DEPS="satooshi/php-coveralls" + - LEGACY_DEPS="phpunit/phpunit" matrix: include: @@ -43,32 +44,30 @@ matrix: - php: 7.1 env: - DEPS=latest - - php: hhvm + - php: nightly env: - DEPS=lowest - - php: hhvm + - php: nightly env: - DEPS=locked - - php: hhvm + - php: nightly env: - DEPS=latest allow_failures: - - php: hhvm - -notifications: - irc: "irc.freenode.org#zftalk.dev" - email: false + - php: nightly before_install: - if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi - travis_retry composer self-update install: - - if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $COVERAGE_DEPS ; fi + - travis_retry composer install $COMPOSER_ARGS --ignore-platform-reqs + - if [[ $TRAVIS_PHP_VERSION =~ ^5.6 ]]; then travis_retry composer update $COMPOSER_ARGS --with-dependencies $LEGACY_DEPS ; fi - if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi - - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-lowest --prefer-stable $COMPOSER_ARGS ; fi - - travis_retry composer install $COMPOSER_ARGS - - composer show + - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update $COMPOSER_ARGS --prefer-lowest --prefer-stable ; fi + - if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $COVERAGE_DEPS ; fi + - stty cols 120 + - COLUMNS=120 composer show script: - if [[ $TEST_COVERAGE == 'true' ]]; then composer test-coverage ; else composer test ; fi @@ -76,3 +75,11 @@ script: after_script: - if [[ $TEST_COVERAGE == 'true' ]]; then composer upload-coverage ; fi + +notifications: + email: false + slack: + rooms: + - secure: "fh+J7c7A9f7Sje2h9M00mw9UyeKQ2l1FyGvOwQ50CPHvf0u7bb1OV3sEqTukiwSNEQNmJ5C3QuJpaxkIeDjI8LJpeNderWeu6NH2O5OedSEElHmc7RsBygfiHM05hWnv10ddDxJ+YtmuNjpkXIoXcBdHby+eRBJ09YStVhnIwQakBbKBH7Idlitn23QYl4VZeA3jTcGsHhCtGjpjDt4sohs/RJWgGfAYTSKcjSLdFWWdg2G8PRPKTyQkR+nFd92lvVeRteg0VzxGJqKXoeJP3B0WYB7emQJho+ly4DZFkL+wJZPtcEHCi/ne9l/OaVy6XGhbiDVXxxpyexD4cmGySdjpsYirXqxjS6V8kfWn3JVbCxipI518zJq5Rb3JOCVcdoo7P/xXqYj+fihMbGfxBorUqwm8uBlCblRGXJ1QcVRsi52u0zMJN+QQ/gYHf0gBoF9IbYvQDeshZT80TnYUy2/om/j9xTUfZMdEKTRQWrj9LbsNKY619gZt2u/b2tbcWdjFiPA/Uxa2VjphHz8LFuHaU43/km4swLhthkPowdZLozuyJjksbJcjH7izh3Hxd8oRxBFrqdfuPgh3owQyW75wvG/TGWnNXMqO66OuXXaJKAomBnVBjGB6DBo3TnPzEyKUkLi54AVQIfaDPqQH8yec5ugogOYrrQDLIT1kdVY=" + on_success: change + on_failure: always From e4eebc4e3ef54b447af600288ae0b4f97aba3bf8 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 9 Jul 2017 23:42:20 +0200 Subject: [PATCH 105/225] Empty lines between use statements of different type (class, function, const) --- .../AlphabeticallySortedUsesSniff.php | 79 ++++++++++++++++++- ...phabeticallySortedUsesUnitTest.1.inc.fixed | 2 + .../AlphabeticallySortedUsesUnitTest.inc | 11 +++ ...AlphabeticallySortedUsesUnitTest.inc.fixed | 14 ++++ .../AlphabeticallySortedUsesUnitTest.php | 5 ++ 5 files changed, 108 insertions(+), 3 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php index 9221eb67..70a20064 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -21,6 +21,7 @@ public function register() public function process(File $phpcsFile, $stackPtr) { $uses = $this->getUseStatements($phpcsFile, $stackPtr); + $tokens = $phpcsFile->getTokens(); $lastUse = null; foreach ($uses as $use) { @@ -44,6 +45,70 @@ public function process(File $phpcsFile, $stackPtr) return; } + // Check empty lines between use statements. + // There must be exactly one empty line between use statements of different type + // and no empty lines between use statements of the same type. + $lineDiff = $tokens[$use['ptrUse']]['line'] - $tokens[$lastUse['ptrUse']]['line']; + if ($lastUse['type'] === $use['type']) { + if ($lineDiff > 1) { + $error = 'There must not be any empty line between use statement of the same type'; + $fix = $phpcsFile->addFixableError($error, $use['ptrUse'], 'EmptyLine'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $lastUse['ptrEnd'] + 1; $i < $use['ptrUse']; ++$i) { + if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false) { + $phpcsFile->fixer->replaceToken($i, ''); + --$lineDiff; + + if ($lineDiff === 1) { + break; + } + } + } + $phpcsFile->fixer->endChangeset(); + } + } elseif ($lineDiff === 0) { + $error = 'Each use statement must be in new line'; + $fix = $phpcsFile->addFixableError($error, $use['ptrUse'], 'TheSameLine'); + + if ($fix) { + $phpcsFile->fixer->addNewline($lastUse['ptrEnd']); + } + } + } else { + if ($lineDiff > 2) { + $error = 'There must be exactly one empty line between use statements of different type'; + $fix = $phpcsFile->addFixableError($error, $use['ptrUse'], 'TooManyEmptyLines'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $lastUse['ptrEnd'] + 1; $i < $use['ptrUse']; ++$i) { + if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false) { + $phpcsFile->fixer->replaceToken($i, ''); + --$lineDiff; + + if ($lineDiff === 2) { + break; + } + } + } + $phpcsFile->fixer->endChangeset(); + } + } elseif ($lineDiff <= 1) { + $error = 'There must be exactly one empty line between use statements of different type'; + $fix = $phpcsFile->addFixableError($error, $use['ptrUse'], 'MissingEmptyLine'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $lineDiff; $i < 2; ++$i) { + $phpcsFile->fixer->addNewline($lastUse['ptrEnd']); + } + $phpcsFile->fixer->endChangeset(); + } + } + } + $lastUse = $use; } } @@ -159,10 +224,18 @@ private function fixAlphabeticalOrder(File $phpcsFile, array $uses) return $this->compareUseStatements($a, $b); }); - $phpcsFile->fixer->addContent($first['ptrUse'], implode($phpcsFile->eolChar, array_map(function ($use) { - return $use['string']; - }, $uses))); + $lastType = reset($uses)['type']; + $content = []; + foreach ($uses as $use) { + if ($lastType !== $use['type']) { + $content[] = $phpcsFile->eolChar . $use['string']; + $lastType = $use['type']; + } else { + $content[] = $use['string']; + } + } + $phpcsFile->fixer->addContent($first['ptrUse'], implode($phpcsFile->eolChar, $content)); $phpcsFile->fixer->endChangeset(); } } diff --git a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed index 727cce42..2a8a7adc 100644 --- a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed +++ b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.1.inc.fixed @@ -9,8 +9,10 @@ use A\TagManager; use B; use C\Response as MyResponse; use C\Response\HtmlResponse; + use function X; use function Y; + use const C; use const D; diff --git a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.inc b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.inc index c5f0e920..2e83e8c1 100644 --- a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.inc +++ b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.inc @@ -25,3 +25,14 @@ namespace Bar { use MyTrait; } } + +namespace C { + use ArrayObject; + + use DateTime; + use function array_keys; + + + + use const PHP_EOL; use const PHP_VERSION_ID; +} diff --git a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.inc.fixed b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.inc.fixed index 541a4487..a3e0fe83 100644 --- a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.inc.fixed +++ b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.inc.fixed @@ -3,8 +3,10 @@ namespace Foo { use A; use B; + use function X; use function Y; + use const C; use const D; @@ -16,8 +18,10 @@ use const D; namespace Bar { use A; use D; + use function B; use function E; + use const C; use const F; @@ -25,3 +29,13 @@ use const F; use MyTrait; } } + +namespace C { + use ArrayObject; + use DateTime; + + use function array_keys; + + use const PHP_EOL; + use const PHP_VERSION_ID; +} diff --git a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php index a6b1b088..45ddd722 100644 --- a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php +++ b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php @@ -16,7 +16,12 @@ public function getErrorList($testFile = '') return [ 5 => 1, + 18 => 1, + 19 => 1, 20 => 1, + 32 => 1, + 33 => 1, + 37 => 2, ]; } From 19e353bb65a32774e9fd40d901587f95e777572b Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 9 Jul 2017 23:46:22 +0200 Subject: [PATCH 106/225] Added InternalFunction sniff This sniff checks if PHP internal functions are imported in the namespace --- .../Sniffs/PHP/InternalFunctionSniff.php | 250 ++++++++++++++++++ .../Sniffs/PHP/InternalFunctionUnitTest.1.inc | 50 ++++ .../PHP/InternalFunctionUnitTest.1.inc.fixed | 59 +++++ .../Sniffs/PHP/InternalFunctionUnitTest.2.inc | 11 + .../PHP/InternalFunctionUnitTest.2.inc.fixed | 15 ++ test/Sniffs/PHP/InternalFunctionUnitTest.inc | 31 +++ .../PHP/InternalFunctionUnitTest.inc.fixed | 38 +++ test/Sniffs/PHP/InternalFunctionUnitTest.php | 52 ++++ 8 files changed, 506 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/PHP/InternalFunctionSniff.php create mode 100644 test/Sniffs/PHP/InternalFunctionUnitTest.1.inc create mode 100644 test/Sniffs/PHP/InternalFunctionUnitTest.1.inc.fixed create mode 100644 test/Sniffs/PHP/InternalFunctionUnitTest.2.inc create mode 100644 test/Sniffs/PHP/InternalFunctionUnitTest.2.inc.fixed create mode 100644 test/Sniffs/PHP/InternalFunctionUnitTest.inc create mode 100644 test/Sniffs/PHP/InternalFunctionUnitTest.inc.fixed create mode 100644 test/Sniffs/PHP/InternalFunctionUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/PHP/InternalFunctionSniff.php b/src/ZendCodingStandard/Sniffs/PHP/InternalFunctionSniff.php new file mode 100644 index 00000000..56ca45e2 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/PHP/InternalFunctionSniff.php @@ -0,0 +1,250 @@ + Hash map of all php built in function names. + */ + private $builtInFunctions; + + /** + * @var File Currently processed file. + */ + private $currentFile; + + /** + * @var string Currently processed namespace. + */ + private $currentNamespace; + + /** + * @var array Array of imported function in current namespace. + */ + private $importedFunction; + + /** + * @var null|int Last use statement position. + */ + private $lastUse; + + public function __construct() + { + $allFunctions = get_defined_functions(); + $this->builtInFunctions = array_flip($allFunctions['internal']); + } + + /** + * @inheritDoc + */ + public function register() + { + return [T_STRING]; + } + + /** + * @inheritDoc + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->currentFile !== $phpcsFile) { + $this->currentFile = $phpcsFile; + $this->currentNamespace = null; + } + + $namespace = $this->getNamespace($phpcsFile, $stackPtr); + if ($this->currentNamespace !== $namespace) { + $this->currentNamespace = $namespace; + $this->importedFunction = $this->getImportedFunctions($phpcsFile, $stackPtr); + } + + $tokens = $phpcsFile->getTokens(); + + // Make sure this is a function call. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); + if (! $next || $tokens[$next]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + $prev = $phpcsFile->findPrevious( + Tokens::$emptyTokens + [T_BITWISE_AND => T_BITWISE_AND, T_NS_SEPARATOR => T_NS_SEPARATOR], + $stackPtr - 1, + null, + true + ); + if ($tokens[$prev]['code'] === T_FUNCTION + || $tokens[$prev]['code'] === T_NEW + || $tokens[$prev]['code'] === T_STRING + || $tokens[$prev]['code'] === T_DOUBLE_COLON + || $tokens[$prev]['code'] === T_OBJECT_OPERATOR + ) { + return; + } + + $content = strtolower($tokens[$stackPtr]['content']); + if (! isset($this->builtInFunctions[$content])) { + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); + if ($tokens[$prev]['code'] === T_NS_SEPARATOR) { + if (isset($this->importedFunction[$content])) { + if (strtolower($this->importedFunction[$content]['fqn']) === $content) { + $error = 'FQN for PHP internal function "%s" is not needed here, function is already imported'; + $data = [ + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'RedundantFQN', $data); + if ($fix) { + $phpcsFile->fixer->replaceToken($prev, ''); + } + } + } else { + $error = 'PHP internal function "%s" must be imported'; + $data = [ + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ImportFQN', $data); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($prev, ''); + $this->importFunction($phpcsFile, $stackPtr, $content); + $phpcsFile->fixer->endChangeset(); + } + } + } else { + if (! isset($this->importedFunction[$content])) { + $error = 'PHP internal function "%s" must be imported'; + $data = [ + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Import', $data); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $this->importFunction($phpcsFile, $stackPtr, $content); + $phpcsFile->fixer->endChangeset(); + } + } + } + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @return string + */ + private function getNamespace(File $phpcsFile, $stackPtr) + { + if ($nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr - 1)) { + $nsEnd = $phpcsFile->findNext([T_NS_SEPARATOR, T_STRING, T_WHITESPACE], $nsStart + 1, null, true); + return trim($phpcsFile->getTokensAsString($nsStart + 1, $nsEnd - $nsStart - 1)); + } + + return ''; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @return array + */ + private function getImportedFunctions(File $phpcsFile, $stackPtr) + { + $first = 0; + $last = $phpcsFile->numTokens; + + $tokens = $phpcsFile->getTokens(); + + $nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr); + if ($nsStart && isset($tokens[$nsStart]['scope_opener'])) { + $first = $tokens[$nsStart]['scope_opener']; + $last = $tokens[$nsStart]['scope_closer']; + } + + $this->lastUse = null; + $functions = []; + + $use = $first; + while ($use = $phpcsFile->findNext(T_USE, $use + 1, $last)) { + if (CodingStandard::isGlobalUse($phpcsFile, $use)) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $use + 1, null, true); + if ($tokens[$next]['code'] === T_STRING + && strtolower($tokens[$next]['content']) === 'function' + ) { + $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); + $end = $phpcsFile->findPrevious( + T_STRING, + $phpcsFile->findNext([T_AS, T_SEMICOLON], $start + 1) - 1 + ); + $endOfStatement = $phpcsFile->findEndOfStatement($next); + $name = $phpcsFile->findPrevious(T_STRING, $endOfStatement - 1); + $fullName = $phpcsFile->getTokensAsString($start, $end - $start + 1); + + $functions[strtolower($tokens[$name]['content'])] = [ + 'name' => $tokens[$name]['content'], + 'fqn' => ltrim($fullName, '\\'), + ]; + + $this->lastUse = $use; + } + } + + if (! $this->lastUse) { + $this->lastUse = $use; + } + } + + return $functions; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @param string $functionName + */ + private function importFunction(File $phpcsFile, $stackPtr, $functionName) + { + if ($this->lastUse) { + $ptr = $phpcsFile->findEndOfStatement($this->lastUse); + } else { + $nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr); + if ($nsStart) { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$nsStart]['scope_opener'])) { + $ptr = $tokens[$nsStart]['scope_opener']; + } else { + $ptr = $phpcsFile->findEndOfStatement($nsStart); + $phpcsFile->fixer->addNewline($ptr); + } + } else { + $ptr = $phpcsFile->findPrevious(T_OPEN_TAG, $stackPtr - 1); + } + } + + $phpcsFile->fixer->addNewline($ptr); + $phpcsFile->fixer->addContent($ptr, sprintf('use function %s;', $functionName)); + if (! $this->lastUse && (! $nsStart || isset($tokens[$nsStart]['scope_opener']))) { + $phpcsFile->fixer->addNewline($ptr); + } + + $this->importedFunction[$functionName] = [ + 'name' => $functionName, + 'fqn' => $functionName, + ]; + } +} diff --git a/test/Sniffs/PHP/InternalFunctionUnitTest.1.inc b/test/Sniffs/PHP/InternalFunctionUnitTest.1.inc new file mode 100644 index 00000000..556dd6cf --- /dev/null +++ b/test/Sniffs/PHP/InternalFunctionUnitTest.1.inc @@ -0,0 +1,50 @@ +count(); +$count = $obj::count(); + +function myFunction() { +} + +if (isset($x) || empty($x)) { + unset($x); + + reset($keys); +} + +$count = &count($array); +$count = \count($array); + +$count = Count($array); + +$keys = Array_Keys($array); +$values = Array_Rand($array); + +$rand = mt_rand(1, 29); +$rand = \MT_rand(1, 100); diff --git a/test/Sniffs/PHP/InternalFunctionUnitTest.inc.fixed b/test/Sniffs/PHP/InternalFunctionUnitTest.inc.fixed new file mode 100644 index 00000000..6c228c3e --- /dev/null +++ b/test/Sniffs/PHP/InternalFunctionUnitTest.inc.fixed @@ -0,0 +1,38 @@ +count(); +$count = $obj::count(); + +function myFunction() { +} + +if (isset($x) || empty($x)) { + unset($x); + + reset($keys); +} + +$count = &count($array); +$count = count($array); + +$count = Count($array); + +$keys = Array_Keys($array); +$values = Array_Rand($array); + +$rand = mt_rand(1, 29); +$rand = MT_rand(1, 100); diff --git a/test/Sniffs/PHP/InternalFunctionUnitTest.php b/test/Sniffs/PHP/InternalFunctionUnitTest.php new file mode 100644 index 00000000..cb8ff12a --- /dev/null +++ b/test/Sniffs/PHP/InternalFunctionUnitTest.php @@ -0,0 +1,52 @@ + 1, + 5 => 1, + 11 => 1, + 12 => 1, + 18 => 1, + 19 => 1, + 26 => 1, + 32 => 1, + 41 => 1, + 49 => 1, + ]; + case 'InternalFunctionUnitTest.2.inc': + return [ + 5 => 1, + 6 => 1, + 8 => 1, + 9 => 1, + ]; + } + + return [ + 3 => 1, + 5 => 1, + 9 => 1, + 19 => 1, + 22 => 1, + 23 => 1, + 25 => 1, + 27 => 1, + 28 => 1, + 30 => 1, + 31 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 731bf854dcf26131a8056a49689fcdfd73b04bf9 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 9 Jul 2017 23:48:53 +0200 Subject: [PATCH 107/225] Import PHP internal functions --- src/ZendCodingStandard/CodingStandard.php | 5 +++++ .../Sniffs/Arrays/FormatSniff.php | 4 ++++ .../AlphabeticallySortedTraitsSniff.php | 9 +++++++++ .../Sniffs/Classes/NoNullValuesSniff.php | 2 ++ .../Sniffs/Classes/TraitUsageSniff.php | 6 ++++++ .../Sniffs/Commenting/DocCommentSniff.php | 7 +++++++ .../Sniffs/Commenting/FunctionCommentSniff.php | 16 ++++++++++++++++ .../ControlStructures/MultilineBraceSniff.php | 4 ++++ .../Sniffs/Formatting/ReferenceSniff.php | 2 ++ .../Sniffs/Formatting/ReturnTypeSniff.php | 4 ++++ .../Formatting/UnnecessaryParenthesesSniff.php | 2 ++ .../Sniffs/Methods/LineAfterSniff.php | 2 ++ .../AlphabeticallySortedUsesSniff.php | 10 ++++++++++ .../ConstAndFunctionKeywordsSniff.php | 2 ++ .../Namespaces/UnusedUseStatementSniff.php | 9 +++++++++ .../UseDoesNotStartWithBackslashSniff.php | 2 ++ .../ValidVariableNameSniff.php | 3 +++ .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 18 ++++++++++++++++++ .../PHP/InstantiatingParenthesisSniff.php | 2 ++ .../Sniffs/PHP/LowerCaseKeywordSniff.php | 2 ++ .../Sniffs/PHP/RedundantSemicolonSniff.php | 3 +++ .../Sniffs/PHP/TypeCastingSniff.php | 4 ++++ .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 3 +++ test/Ruleset.php | 2 ++ test/Sniffs/TestCase.php | 17 +++++++++++++++++ 25 files changed, 140 insertions(+) diff --git a/src/ZendCodingStandard/CodingStandard.php b/src/ZendCodingStandard/CodingStandard.php index e262c770..d58f26bd 100644 --- a/src/ZendCodingStandard/CodingStandard.php +++ b/src/ZendCodingStandard/CodingStandard.php @@ -5,6 +5,11 @@ use PHP_CodeSniffer\Util\Common; use PHP_CodeSniffer\Util\Tokens; +use function preg_match; +use function sprintf; +use function strpos; +use function strtolower; + class CodingStandard { public static $allowedTypes = [ diff --git a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index 8064c736..acd841bd 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -4,6 +4,10 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; +use function str_repeat; +use function strlen; +use function strpos; + class FormatSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php index b758542e..7fb39747 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php @@ -5,6 +5,15 @@ use PHP_CodeSniffer\Sniffs\Sniff; use ZendCodingStandard\CodingStandard; +use function array_map; +use function end; +use function implode; +use function reset; +use function str_replace; +use function strcasecmp; +use function trim; +use function uasort; + class AlphabeticallySortedTraitsSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php b/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php index fef76f3f..422d789a 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php @@ -5,6 +5,8 @@ use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; use PHP_CodeSniffer\Util\Tokens; +use function in_array; + class NoNullValuesSniff extends AbstractVariableSniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php index 5235fe7b..661bad67 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php @@ -6,6 +6,12 @@ use PHP_CodeSniffer\Util\Tokens; use ZendCodingStandard\CodingStandard; +use function array_column; +use function sort; +use function str_replace; +use function strcasecmp; +use function usort; + class TraitUsageSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index 880f78f0..bbb70344 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -4,6 +4,13 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; +use function in_array; +use function preg_match; +use function str_repeat; +use function strlen; +use function strpos; +use function trim; + class DocCommentSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 114a546d..82ff4d49 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -6,6 +6,22 @@ use PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FunctionCommentSniff as PEARFunctionCommentSniff; use ZendCodingStandard\CodingStandard; +use function array_diff; +use function count; +use function explode; +use function implode; +use function in_array; +use function preg_match; +use function spl_object_hash; +use function str_repeat; +use function str_replace; +use function strlen; +use function strpos; +use function strtolower; +use function strtoupper; +use function substr; +use function trim; + class FunctionCommentSniff extends PEARFunctionCommentSniff { /** diff --git a/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php b/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php index af89dfe7..2e9e6aca 100644 --- a/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php +++ b/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php @@ -5,6 +5,10 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use function in_array; +use function str_repeat; +use function strlen; + class MultilineBraceSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php index 97434970..77b6cb94 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php @@ -5,6 +5,8 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use function in_array; + class ReferenceSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php index 3aee0db6..208b0741 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php @@ -5,6 +5,10 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use function in_array; +use function strtolower; +use function trim; + class ReturnTypeSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php index 6acddd81..ca298a24 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -5,6 +5,8 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use function in_array; + class UnnecessaryParenthesesSniff implements Sniff { private $parenthesesAllowedTokens = [ diff --git a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php index 335f0053..c44fadb1 100644 --- a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php +++ b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php @@ -4,6 +4,8 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use function max; + class LineAfterSniff extends AbstractScopeSniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php index 70a20064..dc50041e 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -5,6 +5,16 @@ use PHP_CodeSniffer\Sniffs\Sniff; use ZendCodingStandard\CodingStandard; +use function end; +use function implode; +use function reset; +use function str_replace; +use function strcasecmp; +use function strpos; +use function strtolower; +use function trim; +use function uasort; + class AlphabeticallySortedUsesSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php index 3cc2632f..5b291ab7 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php @@ -6,6 +6,8 @@ use PHP_CodeSniffer\Util\Tokens; use ZendCodingStandard\CodingStandard; +use function strtolower; + class ConstAndFunctionKeywordsSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index c8eabf2b..2ba90989 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -18,6 +18,15 @@ use PHP_CodeSniffer\Util\Tokens; use ZendCodingStandard\CodingStandard; +use function in_array; +use function preg_match; +use function preg_quote; +use function rtrim; +use function strcasecmp; +use function strpos; +use function strtolower; +use function trim; + class UnusedUseStatementSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php index 2271bdc9..f8ca75d9 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php @@ -6,6 +6,8 @@ use PHP_CodeSniffer\Util\Tokens; use ZendCodingStandard\CodingStandard; +use function strtolower; + class UseDoesNotStartWithBackslashSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php index 73269dff..cb4927e4 100644 --- a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php +++ b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -11,6 +11,9 @@ use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; use PHP_CodeSniffer\Util\Common; +use function in_array; +use function ltrim; + class ValidVariableNameSniff extends AbstractVariableSniff { const CODE_CAMEL_CAPS = 'NotCamelCaps'; diff --git a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index 77d60819..30def5c2 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -5,6 +5,24 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use function array_map; +use function array_merge; +use function array_search; +use function explode; +use function get_declared_classes; +use function get_declared_interfaces; +use function get_declared_traits; +use function implode; +use function in_array; +use function ltrim; +use function preg_quote; +use function preg_replace; +use function strlen; +use function strrchr; +use function strtolower; +use function substr; +use function trim; + /** * TODO: Better results for this sniff we will have if the parsed class is imported. * We can "include" the file on process, but probably it is not the best solution. diff --git a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php index 6a62439e..fdaf34d9 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php @@ -5,6 +5,8 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use function array_merge; + class InstantiatingParenthesisSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php b/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php index 30d2cfa2..4b67e35f 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php @@ -3,6 +3,8 @@ use PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\LowerCaseKeywordSniff as GenericLowerCaseKeywordSniff; +use function array_merge; + class LowerCaseKeywordSniff extends GenericLowerCaseKeywordSniff { /** diff --git a/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php b/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php index 6b611c9b..16a4d78c 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php @@ -5,6 +5,9 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use function in_array; +use function strtolower; + class RedundantSemicolonSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php index b4a80db4..99d2d644 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -15,6 +15,10 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use function array_merge; +use function preg_replace; +use function strtolower; + class TypeCastingSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index c24c04b0..f302c626 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -19,6 +19,9 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use function array_merge; +use function strlen; + class CommaSpacingSniff implements Sniff { /** diff --git a/test/Ruleset.php b/test/Ruleset.php index 3a7f983f..26021c09 100644 --- a/test/Ruleset.php +++ b/test/Ruleset.php @@ -1,6 +1,8 @@ Date: Sun, 9 Jul 2017 23:49:55 +0200 Subject: [PATCH 108/225] Updated README.md and added badges (travis build and coverage) --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2a7e94a8..5236b5d6 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ -Zend Framework Coding Standard -============================== +# Zend Framework Coding Standard + +[![Build Status](https://travis-ci.org/zendframework/zend-coding-standard.svg?branch=master)](https://travis-ci.org/zendframework/zend-coding-standard) +[![Coverage Status](https://coveralls.io/repos/github/zendframework/zend-coding-standard/badge.svg?branch=master)](https://coveralls.io/github/zendframework/zend-coding-standard?branch=master) Repository with all coding standard ruleset for Zend Framework repositories. -Installation ------------- +## Installation 1. Install the module via composer by running: @@ -40,8 +41,7 @@ You can add or exclude some locations in that file. For a reference please see: https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml -Usage ------ +## Usage * To run checks only: From 47304d1c4165c16482d5727f44a811dc6b3c02de Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 12 Jul 2017 10:47:40 +0200 Subject: [PATCH 109/225] Renamed sniff InternalFunction to ImportInternalFunction and disabled by default --- ruleset.xml | 5 +++++ ...nalFunctionSniff.php => ImportInternalFunctionSniff.php} | 2 +- ...nUnitTest.1.inc => ImportInternalFunctionUnitTest.1.inc} | 0 ...inc.fixed => ImportInternalFunctionUnitTest.1.inc.fixed} | 0 ...nUnitTest.2.inc => ImportInternalFunctionUnitTest.2.inc} | 0 ...inc.fixed => ImportInternalFunctionUnitTest.2.inc.fixed} | 0 ...ctionUnitTest.inc => ImportInternalFunctionUnitTest.inc} | 0 ...t.inc.fixed => ImportInternalFunctionUnitTest.inc.fixed} | 0 ...ctionUnitTest.php => ImportInternalFunctionUnitTest.php} | 6 +++--- 9 files changed, 9 insertions(+), 4 deletions(-) rename src/ZendCodingStandard/Sniffs/PHP/{InternalFunctionSniff.php => ImportInternalFunctionSniff.php} (99%) rename test/Sniffs/PHP/{InternalFunctionUnitTest.1.inc => ImportInternalFunctionUnitTest.1.inc} (100%) rename test/Sniffs/PHP/{InternalFunctionUnitTest.1.inc.fixed => ImportInternalFunctionUnitTest.1.inc.fixed} (100%) rename test/Sniffs/PHP/{InternalFunctionUnitTest.2.inc => ImportInternalFunctionUnitTest.2.inc} (100%) rename test/Sniffs/PHP/{InternalFunctionUnitTest.2.inc.fixed => ImportInternalFunctionUnitTest.2.inc.fixed} (100%) rename test/Sniffs/PHP/{InternalFunctionUnitTest.inc => ImportInternalFunctionUnitTest.inc} (100%) rename test/Sniffs/PHP/{InternalFunctionUnitTest.inc.fixed => ImportInternalFunctionUnitTest.inc.fixed} (100%) rename test/Sniffs/PHP/{InternalFunctionUnitTest.php => ImportInternalFunctionUnitTest.php} (85%) diff --git a/ruleset.xml b/ruleset.xml index 35c6319a..cc78c114 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -1,4 +1,9 @@ + + + + + diff --git a/src/ZendCodingStandard/Sniffs/PHP/InternalFunctionSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php similarity index 99% rename from src/ZendCodingStandard/Sniffs/PHP/InternalFunctionSniff.php rename to src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php index 56ca45e2..f1e65c4f 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/InternalFunctionSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php @@ -13,7 +13,7 @@ use function strtolower; use function trim; -class InternalFunctionSniff implements Sniff +class ImportInternalFunctionSniff implements Sniff { /** * @var array Hash map of all php built in function names. diff --git a/test/Sniffs/PHP/InternalFunctionUnitTest.1.inc b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.1.inc similarity index 100% rename from test/Sniffs/PHP/InternalFunctionUnitTest.1.inc rename to test/Sniffs/PHP/ImportInternalFunctionUnitTest.1.inc diff --git a/test/Sniffs/PHP/InternalFunctionUnitTest.1.inc.fixed b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.1.inc.fixed similarity index 100% rename from test/Sniffs/PHP/InternalFunctionUnitTest.1.inc.fixed rename to test/Sniffs/PHP/ImportInternalFunctionUnitTest.1.inc.fixed diff --git a/test/Sniffs/PHP/InternalFunctionUnitTest.2.inc b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.2.inc similarity index 100% rename from test/Sniffs/PHP/InternalFunctionUnitTest.2.inc rename to test/Sniffs/PHP/ImportInternalFunctionUnitTest.2.inc diff --git a/test/Sniffs/PHP/InternalFunctionUnitTest.2.inc.fixed b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.2.inc.fixed similarity index 100% rename from test/Sniffs/PHP/InternalFunctionUnitTest.2.inc.fixed rename to test/Sniffs/PHP/ImportInternalFunctionUnitTest.2.inc.fixed diff --git a/test/Sniffs/PHP/InternalFunctionUnitTest.inc b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.inc similarity index 100% rename from test/Sniffs/PHP/InternalFunctionUnitTest.inc rename to test/Sniffs/PHP/ImportInternalFunctionUnitTest.inc diff --git a/test/Sniffs/PHP/InternalFunctionUnitTest.inc.fixed b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.inc.fixed similarity index 100% rename from test/Sniffs/PHP/InternalFunctionUnitTest.inc.fixed rename to test/Sniffs/PHP/ImportInternalFunctionUnitTest.inc.fixed diff --git a/test/Sniffs/PHP/InternalFunctionUnitTest.php b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.php similarity index 85% rename from test/Sniffs/PHP/InternalFunctionUnitTest.php rename to test/Sniffs/PHP/ImportInternalFunctionUnitTest.php index cb8ff12a..f99ebb4b 100644 --- a/test/Sniffs/PHP/InternalFunctionUnitTest.php +++ b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.php @@ -3,12 +3,12 @@ use ZendCodingStandardTest\Sniffs\TestCase; -class InternalFunctionUnitTest extends TestCase +class ImportInternalFunctionUnitTest extends TestCase { public function getErrorList($testFile = '') { switch ($testFile) { - case 'InternalFunctionUnitTest.1.inc': + case 'ImportInternalFunctionUnitTest.1.inc': return [ 4 => 1, 5 => 1, @@ -21,7 +21,7 @@ public function getErrorList($testFile = '') 41 => 1, 49 => 1, ]; - case 'InternalFunctionUnitTest.2.inc': + case 'ImportInternalFunctionUnitTest.2.inc': return [ 5 => 1, 6 => 1, From bf10d1c6d76c9ec008d2588d9a82a9db6752cb28 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 12 Jul 2017 10:47:50 +0200 Subject: [PATCH 110/225] Removed redundant TODO comment --- test/Ruleset.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Ruleset.php b/test/Ruleset.php index 26021c09..a355eae8 100644 --- a/test/Ruleset.php +++ b/test/Ruleset.php @@ -13,6 +13,6 @@ public function registerSniffs($files, $restrictions, $exclusions) $restrictions[$newClassName] = $bool; } - parent::registerSniffs($files, $restrictions, $exclusions); // TODO: Change the autogenerated stub + parent::registerSniffs($files, $restrictions, $exclusions); } } From 9373f0fe4bc3660064372fa11e0ffbd7fbc175bf Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 12 Jul 2017 10:48:12 +0200 Subject: [PATCH 111/225] Removed slack integration in travis configuration --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index e5d5ff1e..38e987cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -78,8 +78,3 @@ after_script: notifications: email: false - slack: - rooms: - - secure: "fh+J7c7A9f7Sje2h9M00mw9UyeKQ2l1FyGvOwQ50CPHvf0u7bb1OV3sEqTukiwSNEQNmJ5C3QuJpaxkIeDjI8LJpeNderWeu6NH2O5OedSEElHmc7RsBygfiHM05hWnv10ddDxJ+YtmuNjpkXIoXcBdHby+eRBJ09YStVhnIwQakBbKBH7Idlitn23QYl4VZeA3jTcGsHhCtGjpjDt4sohs/RJWgGfAYTSKcjSLdFWWdg2G8PRPKTyQkR+nFd92lvVeRteg0VzxGJqKXoeJP3B0WYB7emQJho+ly4DZFkL+wJZPtcEHCi/ne9l/OaVy6XGhbiDVXxxpyexD4cmGySdjpsYirXqxjS6V8kfWn3JVbCxipI518zJq5Rb3JOCVcdoo7P/xXqYj+fihMbGfxBorUqwm8uBlCblRGXJ1QcVRsi52u0zMJN+QQ/gYHf0gBoF9IbYvQDeshZT80TnYUy2/om/j9xTUfZMdEKTRQWrj9LbsNKY619gZt2u/b2tbcWdjFiPA/Uxa2VjphHz8LFuHaU43/km4swLhthkPowdZLozuyJjksbJcjH7izh3Hxd8oRxBFrqdfuPgh3owQyW75wvG/TGWnNXMqO66OuXXaJKAomBnVBjGB6DBo3TnPzEyKUkLi54AVQIfaDPqQH8yec5ugogOYrrQDLIT1kdVY=" - on_success: change - on_failure: always From f3e63f15d2bb9382c74c83ee82d0048b5b81f10e Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 14 Jul 2017 23:03:55 +0200 Subject: [PATCH 112/225] Fixed indents in sniff --- .../UnnecessaryParenthesesSniff.php | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php index ca298a24..4ba9841c 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -110,14 +110,14 @@ public function process(File $phpcsFile, $stackPtr) if (in_array($tokens[$prev]['code'], Tokens::$castTokens, true)) { $op = $phpcsFile->findNext( Tokens::$assignmentTokens - + Tokens::$booleanOperators - + Tokens::$equalityTokens - + Tokens::$operators - + [ - T_INLINE_ELSE => T_INLINE_ELSE, - T_INLINE_THEN => T_INLINE_THEN, - T_INSTANCEOF => T_INSTANCEOF, - ], + + Tokens::$booleanOperators + + Tokens::$equalityTokens + + Tokens::$operators + + [ + T_INLINE_ELSE => T_INLINE_ELSE, + T_INLINE_THEN => T_INLINE_THEN, + T_INSTANCEOF => T_INSTANCEOF, + ], $stackPtr + 1, $closePtr ); @@ -136,13 +136,13 @@ public function process(File $phpcsFile, $stackPtr) if (in_array($tokens[$prev]['code'], $prevTokens, true)) { $op = $phpcsFile->findNext( Tokens::$assignmentTokens - + Tokens::$booleanOperators - + Tokens::$equalityTokens - + Tokens::$operators - + [ - T_INLINE_ELSE => T_INLINE_ELSE, - T_INLINE_THEN => T_INLINE_THEN, - ], + + Tokens::$booleanOperators + + Tokens::$equalityTokens + + Tokens::$operators + + [ + T_INLINE_ELSE => T_INLINE_ELSE, + T_INLINE_THEN => T_INLINE_THEN, + ], $stackPtr + 1, $closePtr ); @@ -157,15 +157,15 @@ public function process(File $phpcsFile, $stackPtr) if (in_array($tokens[$prev]['code'], Tokens::$equalityTokens, true)) { $op = $phpcsFile->findNext( Tokens::$assignmentTokens - + Tokens::$booleanOperators - + [ - T_BITWISE_AND => T_BITWISE_AND, - T_BITWISE_OR => T_BITWISE_OR, - T_BITWISE_XOR => T_BITWISE_XOR, - T_COALESCE => T_COALESCE, - T_INLINE_ELSE => T_INLINE_ELSE, - T_INLINE_THEN => T_INLINE_THEN, - ], + + Tokens::$booleanOperators + + [ + T_BITWISE_AND => T_BITWISE_AND, + T_BITWISE_OR => T_BITWISE_OR, + T_BITWISE_XOR => T_BITWISE_XOR, + T_COALESCE => T_COALESCE, + T_INLINE_ELSE => T_INLINE_ELSE, + T_INLINE_THEN => T_INLINE_THEN, + ], $stackPtr + 1, $closePtr ); @@ -184,11 +184,11 @@ public function process(File $phpcsFile, $stackPtr) if (in_array($tokens[$prev]['code'], [T_INLINE_THEN, T_INLINE_ELSE], true)) { $op = $phpcsFile->findNext( Tokens::$assignmentTokens - + Tokens::$booleanOperators - + [ - T_INLINE_ELSE => T_INLINE_ELSE, - T_INLINE_THEN => T_INLINE_THEN, - ], + + Tokens::$booleanOperators + + [ + T_INLINE_ELSE => T_INLINE_ELSE, + T_INLINE_THEN => T_INLINE_THEN, + ], $stackPtr + 1, $closePtr ); From a1157c616b4a2f468480539e99477c9b58e9720b Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 14 Jul 2017 23:08:05 +0200 Subject: [PATCH 113/225] Added *experimental* sniff WhiteSpace.ScopeIndent sniff It implements stricter rules and replaces two other sniffs: - Generic.WhiteSpace.ScopeIndent - PSR2.Methods.FunctionCallSignature.Indent - Squiz.WhiteSpace.ScopeClosingBrace.Indent It requires more tests to find out if all cases are there already included and if it works correctly with multiple open/close php tags. This sniff is not working correctly in all cases, because of bug: https://github.com/squizlabs/PHP_CodeSniffer/pull/1532 It will be fixed in PHP_CodeSniffer 3.0.2. --- .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 595 ++++++++++++++++++ src/ZendCodingStandard/ruleset.xml | 4 + .../Sniffs/WhiteSpace/ScopeIndentUnitTest.inc | 402 ++++++++++++ .../WhiteSpace/ScopeIndentUnitTest.inc.fixed | 400 ++++++++++++ .../Sniffs/WhiteSpace/ScopeIndentUnitTest.php | 137 ++++ 5 files changed, 1538 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php create mode 100644 test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc create mode 100644 test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed create mode 100644 test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php new file mode 100644 index 00000000..c92c9519 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -0,0 +1,595 @@ + T_IF, + T_ELSEIF => T_ELSEIF, + T_WHILE => T_WHILE, + T_FOR => T_FOR, + T_FOREACH => T_FOREACH, + ]; + + private $endOfStatement = [ + T_SEMICOLON, + T_CLOSE_CURLY_BRACKET, + T_OPEN_CURLY_BRACKET, + T_OPEN_TAG, + T_COLON, + T_GOTO_LABEL, + T_COMMA, + T_OPEN_PARENTHESIS, + ]; + + private $caseEndToken = [ + T_BREAK, + T_CONTINUE, + T_RETURN, + T_THROW, + T_EXIT, + ]; + + private $breakToken; + + private $functionToken; + + public function __construct() + { + $this->breakToken = Tokens::$operators + + Tokens::$assignmentTokens + + Tokens::$booleanOperators + + Tokens::$comparisonTokens + + [ + T_SEMICOLON => T_SEMICOLON, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COMMA => T_COMMA, + T_INLINE_ELSE => T_INLINE_ELSE, + T_INLINE_THEN => T_INLINE_THEN, + T_STRING_CONCAT => T_STRING_CONCAT, + ]; + + $this->functionToken = Tokens::$functionNameTokens + + [ + T_SELF => T_SELF, + T_STATIC => T_STATIC, + T_VARIABLE => T_VARIABLE, + T_CLOSE_CURLY_BRACKET => T_CLOSE_PARENTHESIS, + T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS, + T_USE => T_USE, + T_CLOSURE => T_CLOSURE, + ]; + } + + /** + * @inheritDoc + */ + public function register() + { + return [ + T_OPEN_TAG, + ]; + } + + /** + * @inheritDoc + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $depth = 0; + $extras = []; + $previousIndent = null; + + // calculate indent of php open tag + $html = $phpcsFile->findFirstOnLine(T_INLINE_HTML, $stackPtr); + $trimmed = ltrim($tokens[$html]['content']); + if ($html === false || $trimmed === '') { + $extraIndent = $tokens[$stackPtr]['column'] - 1; + } else { + $extraIndent = strlen($tokens[$html]['content']) - strlen($trimmed); + } + + for ($i = $stackPtr + 1; $i < $phpcsFile->numTokens; ++$i) { + if (in_array($tokens[$i]['code'], Tokens::$booleanOperators, true)) { + $next = $phpcsFile->findNext( + Tokens::$emptyTokens + [T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS], + $i + 1, + null, + true + ); + + if ($tokens[$next]['line'] > $tokens[$i]['line']) { + $error = 'Boolean operator found at the end of the line.'; + $fix = $phpcsFile->addFixableError($error, $i, 'BooleanOperatorAtTheEnd'); + + if ($fix) { + $lastNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, $next - 1, null, true); + $string = $phpcsFile->getTokensAsString($i, $lastNonEmpty - $i + 1); + + if (substr($string, -1) !== '(') { + $string .= ' '; + } + + $phpcsFile->fixer->beginChangeset(); + $j = $i - 1; + while ($tokens[$j]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($j, ''); + --$j; + } + for ($j = $i; $j <= $lastNonEmpty; ++$j) { + $phpcsFile->fixer->replaceToken($j, ''); + } + $phpcsFile->fixer->addContentBefore($next, $string); + $phpcsFile->fixer->endChangeset(); + } + + continue; + } + } + + // skip some tags + if ($tokens[$i]['code'] === T_INLINE_HTML) { + // || $tokens[$i]['code'] === T_CLOSE_TAG + // || $tokens[$i]['code'] === T_OPEN_TAG + continue; + } + + if (($tokens[$i]['code'] === T_CONSTANT_ENCAPSED_STRING + || $tokens[$i]['code'] === T_DOUBLE_QUOTED_STRING) + && $tokens[$i - 1]['code'] === $tokens[$i]['code'] + ) { + continue; + } + + // || $tokens[$i]['code'] === T_ANON_CLASS + if ($tokens[$i]['code'] === T_CLASS) { + $i = $tokens[$i]['scope_opener']; + continue; + } + + // @todo: multi-open-tags + if ($tokens[$i]['code'] === T_OPEN_TAG) { + // $error = 'This sniff does not support files with multiple PHP open tags.'; + // $phpcsFile->addError($error, $i, 'UnsupportedFile'); + // return $phpcsFile->numTokens; + // if ($depth === 0) { + $extraIndent = max($tokens[$i]['column'] - 1 - ($depth * $this->indent), 0); + $extraIndent = (int) (ceil($extraIndent / $this->indent) * $this->indent); + // } + continue; + } + + // skip doc block comment + if ($tokens[$i]['code'] === T_DOC_COMMENT_OPEN_TAG) { + $i = $tokens[$i]['comment_closer']; + continue; + } + + // skip short arrays + if ($tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) { + $i = $tokens[$i]['bracket_closer']; + continue; + } + + // skip long arrays + if ($tokens[$i]['code'] === T_ARRAY) { + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + + // skip heredoc/nowdoc + if ($tokens[$i]['code'] === T_START_HEREDOC + || $tokens[$i]['code'] === T_START_NOWDOC + ) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + if (empty($tokens[$i]['parenthesis_owner'])) { + $parenthesisOwner = $phpcsFile->findPrevious(Tokens::$emptyTokens, $i - 1, null, true); + } else { + $parenthesisOwner = $tokens[$i]['parenthesis_owner']; + } + + if (in_array($tokens[$parenthesisOwner]['code'], $this->controlStructures, true)) { + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + } + + if (isset($extras[$i])) { + $extraIndent -= $extras[$i]; + unset($extras[$i]); + } + + if ($tokens[$i]['code'] === T_OBJECT_OPERATOR) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $i - 1, null, true); + + if ($tokens[$prev]['line'] === $tokens[$i]['line']) { + if (($prevObjectOperator = $this->hasPrevObjectOperator($phpcsFile, $i)) + && $tokens[$prevObjectOperator]['line'] < $tokens[$i]['line'] + ) { + // add line break before + $error = 'Object operator must be in new line'; + $fix = $phpcsFile->addFixableError($error, $i, 'ObjectOperator'); + + if ($fix) { + $phpcsFile->fixer->addNewlineBefore($i); + } + } + + $next = $phpcsFile->findNext( + Tokens::$emptyTokens + [ + T_STRING, + T_VARIABLE, + T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET, + ], + $i + 1, + null, + true + ); + + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS + && $tokens[$tokens[$next]['parenthesis_closer']]['line'] > $tokens[$next]['line'] + ) { + $after = $phpcsFile->findNext( + Tokens::$emptyTokens, + $tokens[$next]['parenthesis_closer'] + 1, + null, + true + ); + if ($tokens[$after]['code'] === T_OBJECT_OPERATOR) { + $column = $tokens[$i]['column']; + $newEI = $column - 1 - $extraIndent - $tokens[$i]['level'] * $this->indent; + $extraIndent += $newEI; + if (isset($extras[$after])) { + $extras[$after] += $newEI; + } else { + $extras[$after] = $newEI; + } + } + } + } + } + + if ($tokens[$i]['column'] === 1 + && ($next = $phpcsFile->findNext(T_WHITESPACE, $i, null, true)) + && $tokens[$next]['line'] === $tokens[$i]['line'] + ) { + $depth = $tokens[$next]['level']; + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $i - 1, null, true); + + $expectedIndent = $depth * $this->indent; + if (in_array($tokens[$next]['code'], $this->caseEndToken, true) + && isset($tokens[$next]['scope_closer']) + && $tokens[$next]['scope_closer'] === $next + ) { + $endOfStatement = $phpcsFile->findEndOfStatement($next); + if (isset($extras[$endOfStatement])) { + $extras[$endOfStatement] += $this->indent; + } else { + $extras[$endOfStatement] = $this->indent; + } + + $extraIndent += $this->indent;// expectedIndent += $this->indent; + } elseif ($tokens[$next]['code'] === T_CLOSE_PARENTHESIS) { + if (isset($extras[$next])) { + $extraIndent -= $extras[$next]; + unset($extras[$next]); + } + + $opener = $tokens[$next]['parenthesis_opener']; + $owner = $phpcsFile->findPrevious(Tokens::$emptyTokens, $opener - 1, null, true); + + // if it is not a function call + if (! in_array($tokens[$owner]['code'], $this->functionToken, true)) { + $error = 'Closing parenthesis must be in previous line.'; + $fix = $phpcsFile->addFixableError($error, $next, 'ClosingParenthesis'); + + if ($fix) { + $semicolon = $phpcsFile->findNext(Tokens::$emptyTokens, $next + 1, null, true); + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($next, ''); + $phpcsFile->fixer->addContent($prev, $tokens[$next]['content']); + if ($tokens[$semicolon]['code'] === T_SEMICOLON) { + $phpcsFile->fixer->addContent($prev, ';'); + $phpcsFile->fixer->replaceToken($semicolon, ''); + $j = $semicolon + 1; + } else { + $j = $next + 1; + } + while ($tokens[$j]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($j, ''); + ++$j; + + if ($tokens[$j]['line'] > $tokens[$next]['line']) { + break; + } + } + $phpcsFile->fixer->endChangeset(); + } + + continue; + } + } elseif ($tokens[$next]['code'] === T_OBJECT_OPERATOR) { + if (isset($extras[$next])) { + $extraIndent -= $extras[$next]; + unset($extras[$next]); + } + + $np = $this->np($phpcsFile, $next); + if ($fp = $this->fp($phpcsFile, $next)) { + $newEI = $fp - 1 - $expectedIndent - $extraIndent; + $extraIndent += $newEI; + if (isset($extras[$np])) { + $extras[$np] += $newEI; + } else { + $extras[$np] = $newEI; + } + } else { + $extraIndent += $this->indent; + if (isset($extras[$np])) { + $extras[$np] += $this->indent; + } else { + $extras[$np] = $this->indent; + } + } + } elseif ($tokens[$next]['code'] === T_INLINE_THEN) { + $expectedIndent = $previousIndent - $extraIndent + $this->indent; + } elseif ($tokens[$next]['code'] === T_INLINE_ELSE) { + $count = 0; + $t = $i; + while ($t = $phpcsFile->findPrevious([T_INLINE_THEN, T_INLINE_ELSE], $t - 1)) { + if ($tokens[$t]['code'] === T_INLINE_ELSE) { + ++$count; + } else { + --$count; + + if ($count < 0) { + break; + } + } + } + + $first = $phpcsFile->findFirstOnLine([], $t, true); + if ($tokens[$first]['code'] !== T_WHITESPACE) { + $expectedIndent = $this->indent; + } else { + $expectedIndent = strlen($tokens[$first]['content']) - $extraIndent; + + $firstNonEmpty = $phpcsFile->findFirstOnLine(Tokens::$emptyTokens, $t, true); + if ($t !== $firstNonEmpty) { + $expectedIndent += $this->indent; + } + } + } elseif (! in_array($tokens[$prev]['code'], $this->endOfStatement, true) + && $tokens[$next]['code'] !== T_OPEN_CURLY_BRACKET + ) { + if ($expectedIndent + $extraIndent <= $previousIndent) { + $expectedIndent = ($depth + 1) * $this->indent; + } + } + + $expectedIndent += $extraIndent; + $previousIndent = $expectedIndent; + + if ($tokens[$i]['code'] === T_WHITESPACE + && strpos($tokens[$i]['content'], $phpcsFile->eolChar) === false + && strlen($tokens[$i]['content']) !== $expectedIndent + ) { + $error = 'Invalid indent. Expected %d spaces, found %d'; + $data = [ + $expectedIndent, + strlen($tokens[$i]['content']), + ]; + $fix = $phpcsFile->addFixableError($error, $i, 'InvalidIndent', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($i, str_repeat(' ', max($expectedIndent, 0))); + } + } elseif ($tokens[$i]['code'] === T_COMMENT + && preg_match('/^(\s*)\*/', $tokens[$i]['content'], $match) + ) { + if (strlen($match[1]) !== $expectedIndent + 1) { + $error = 'Invalid comment indent. Expected %d spaces, found %d'; + $data = [ + $expectedIndent + 1, + strlen($match[1]), + ]; + $fix = $phpcsFile->addFixableError($error, $i, 'CommentIndent', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken( + $i, + str_repeat(' ', max($expectedIndent, 0) + 1) . ltrim($tokens[$i]['content']) + ); + } + } + } elseif ($tokens[$i]['code'] !== T_WHITESPACE + && $expectedIndent + && ($tokens[$i]['code'] !== T_COMMENT + || preg_match('/^\s*(\/\/|#)/', $tokens[$i]['content'])) + ) { + $error = 'Missing indent. Expected %d spaces'; + $data = [$expectedIndent]; + $fix = $phpcsFile->addFixableError($error, $i, 'MissingIndent', $data); + + if ($fix) { + $phpcsFile->fixer->addContentBefore($i, str_repeat(' ', max($expectedIndent, 0))); + } + } + } + + // count extra indent + $ei = 0; + if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS + || ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET + && isset($tokens[$i]['scope_closer'])) + ) { + $xEnd = $tokens[$i]['code'] === T_OPEN_PARENTHESIS + ? $tokens[$i]['parenthesis_closer'] + : $tokens[$i]['scope_closer']; + + // no extra indent if closing parenthesis/bracket is in the same line + if ($tokens[$i]['line'] === $tokens[$xEnd]['line']) { + continue; + } + + // if there is another open bracket in that line, skip current one. + $another = $i; + while (($another = $phpcsFile->findNext([T_OPEN_PARENTHESIS, T_OPEN_CURLY_BRACKET], $another + 1)) + && $tokens[$another]['line'] === $tokens[$i]['line'] + ) { + if (($tokens[$another]['code'] === T_OPEN_PARENTHESIS + && $tokens[$tokens[$another]['parenthesis_closer']]['line'] > $tokens[$another]['line']) + || (isset($tokens[$another]['scope_closer']) + && $tokens[$tokens[$another]['scope_closer']]['line'] > $tokens[$another]['line']) + ) { + continue 2; + } + } + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $i, true); + + $firstInNextLine = $i; + while ($tokens[$firstInNextLine]['line'] === $tokens[$i]['line'] + || $tokens[$firstInNextLine]['code'] === T_WHITESPACE + ) { + ++$firstInNextLine; + } + + if ($tokens[$first]['level'] === $tokens[$firstInNextLine]['level'] + && $tokens[$firstInNextLine]['code'] !== T_CLOSE_CURLY_BRACKET + ) { + $ei += $this->indent; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $i + 1, null, true); + + if ($tokens[$next]['line'] > $tokens[$i]['line']) { + // current line indent + $whitespace = $phpcsFile->findFirstOnLine([], $i, true); + if ($tokens[$whitespace]['code'] === T_WHITESPACE) { + $sum = strlen($tokens[$whitespace]['content']) + - $tokens[$first]['level'] * $this->indent + - $extraIndent; + + if ($sum > 0) { + $ei += $sum; + } + } + } + } + + if ($ei) { + $extraIndent += $ei; + if (isset($extras[$xEnd])) { + $extras[$xEnd] += $ei; + } else { + $extras[$xEnd] = $ei; + } + } + } + + return $phpcsFile->numTokens; + } + + /** + * @param File $phpcsFile + * @param int $ptr + * @return int|null + */ + private function fp(File $phpcsFile, $ptr) + { + if ($this->alignObjectOperators) { + $tokens = $phpcsFile->getTokens(); + + while (--$ptr) { + if ($tokens[$ptr]['code'] === T_CLOSE_PARENTHESIS) { + $ptr = $tokens[$ptr]['parenthesis_opener']; + } elseif ($tokens[$ptr]['code'] === T_CLOSE_CURLY_BRACKET) { + $ptr = $tokens[$ptr]['bracket_opener']; + } elseif ($tokens[$ptr]['code'] === T_OBJECT_OPERATOR) { + return $tokens[$ptr]['column']; + } elseif ($tokens[$ptr]['code'] === T_SEMICOLON) { + break; + } + } + } + + return null; + } + + /** + * @param File $phpcsFile + * @param int $ptr + * @return int|null + */ + private function np(File $phpcsFile, $ptr) + { + $tokens = $phpcsFile->getTokens(); + + while (++$ptr) { + if ($tokens[$ptr]['code'] === T_OPEN_PARENTHESIS) { + $ptr = $tokens[$ptr]['parenthesis_closer']; + } elseif ($tokens[$ptr]['code'] === T_OPEN_CURLY_BRACKET) { + $ptr = $tokens[$ptr]['bracket_closer']; + } elseif ($tokens[$ptr]['code'] === T_OBJECT_OPERATOR + || $tokens[$ptr]['code'] === T_SEMICOLON + ) { + return $ptr; + } + } + + return null; + } + + /** + * @param File $phpcsFile + * @param int $ptr + * @return int|null + */ + private function hasPrevObjectOperator(File $phpcsFile, $ptr) + { + $tokens = $phpcsFile->getTokens(); + + while (--$ptr) { + if ($tokens[$ptr]['code'] === T_CLOSE_PARENTHESIS) { + $ptr = $tokens[$ptr]['parenthesis_opener']; + } elseif ($tokens[$ptr]['code'] === T_CLOSE_CURLY_BRACKET) { + $ptr = $tokens[$ptr]['bracket_opener']; + } elseif ($tokens[$ptr]['code'] === T_OBJECT_OPERATOR) { + return $ptr; + } elseif (in_array($tokens[$ptr]['code'], $this->breakToken, true)) { + break; + } + } + + return null; + } +} diff --git a/src/ZendCodingStandard/ruleset.xml b/src/ZendCodingStandard/ruleset.xml index fe4e7b48..6364f900 100755 --- a/src/ZendCodingStandard/ruleset.xml +++ b/src/ZendCodingStandard/ruleset.xml @@ -15,6 +15,10 @@ + + + + diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc new file mode 100644 index 00000000..fc382a26 --- /dev/null +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc @@ -0,0 +1,402 @@ + $b) { +return 1; +} + +return [ + 1, + 2, + ]; +} +} + +switch (true) { +case '1': +echo 1; +break; +case '2': +echo 2; +break; +default: +switch ($a) { +default: +case 0: +echo 9; +return 17; +case 1: +break; +} +break; +} + +usort($a, function($x, $y) { + return $x > $y; +}); + +function x($a) { + /* + * some comment + */ + $y = $a; + + return $y; +} + +class Test2 { + public $var = <<call($a, $b) + ->another($x) + ->oneMore($d); + +(new DateTime()) + ->modify('-1 day') + ->modify('-1 hour'); + +$m = (new DateTime())->modify('-1 second') + ->modify('+1 second'); + +$val = $class->{$method}($value) + ->{$value}; + +$v = $a->{$m}(1) + ->{$d} + ->date + ->modify('-1 day') + ->format('Y-m-d'); + +$f = function () use ( + $foo, + $bar +) { + return $foo + $bar; +}; + +LABEL: + + $something = 'porter'; + +OTHER: + + $other = 'label'; + +$g = $t->method() + ->another(function () { + $x = 13; + + return $x; + }); + +$concatenation = 'string' + . 'next part'; + +$sum = $a + + $b; + +class B { + public function foo() + { + return function ($stream, $streamIndex) { + return preg_match('#(.*?)\r?\n#', $stream, $matches, null, $streamIndex) === 1 + ? $matches[1] + : substr($stream, $streamIndex); + }; + } + + public function bar($parameters) + { + return array_filter( + $parameters, + function (array $parameter) { + return PHP_VERSION_ID >= 70100 + || ( + false === strpos($parameter[2], '?') + && ! in_array(strtolower($parameter[2]), ['void', 'iterable']) + ); + } + ); + } + + public function tar($abc, $def) + { + /* + this part is commented out + and doesn't matter + what + indent +do we have here. + + */ + return PHP_VERSION_ID >= 70100 && ( + $abc + || $def + ); + } + + private function test2($services) + { + return function () use ($services) { + return $services->get('Application') + ->method1() + ->method2(); + }; + } +} + +switch ($a) { + // POST + case 'POST': + $do = 'something'; + break; + // GET + case 'GET': + // my comment here + break; +// All others + default: + $do = 'nothing'; + break; +} + +echo "This is a long +string that spans $numLines lines + without indenting. +"; + +$oldArray = array( + 'it', 'does', + 'not', + 'check', + 'arrays' +); + +class Test3 +{ + public static $a; + + public static function xyz($b) + { + if (static::$a[$b] === null) { + static::$a[$b] = new static( + 'it', + 'is', + 'not checked in that sniff' + ); + } + } +} + +$obj->{$m}( + 'skip', + 'it' +); + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): + if ($bar) $foo = 1; + elseif ($baz) $foo = 2; +endif; + +usort( + $a, + function ( + $x, + $y + ) { + return $x > $y; + } +); + +$var = $foo + && $bar + && ($baz + || $key); + +$num = $multi + * ($val1 + + $val2) + + $int; + +$closure = function ( + $a, + $b, + $c +) { + if ($a + $b > $c) { + return $a + && ($b + || $c); + } + + return $b && ($a + || $c); +}; + +switch ($r) { +case self::TYPE: +$var = null; +if ($x) { + return 1; +} +exit; +case self::GO; +return function () use ($r) { +if ($r) { +throw new \InvalidArgumentException( +sprintf('Error %s', 'value') +); +} + +return function ($a, $b) { +return $a <=> $b; +}; +}; +case self::DEF: + default: +$var = 1; +throw new \Exception(sprintf( +'Type "%s" is unknown or cannot be used as property default value.', +get_class($value) +)); +} + +(function ($a, $b) { +return function ($c, $d) use ($a, $b) { +echo $a, $b, $c, $d; +}; +})( + 'a', +'b' +)( + 'c', +'d' +); + +(new \DateTime([ + 'something', +]))->format('ymd'); + +$myVariable + ->call(sprintf( + 'Text %s', + 'value' + )); + +class MyClass +{ + public function test() + { + } +} + +$mock->expects( + $this->any() +) +->method('get') +->will($this->throwException()); + +$mock->expects($this->any()) +->method( +'get' +) +->will($this->throwException()); + +$mock +->expects($this->any()) +->method( +'get' +) +->will($this->throwException()); + +$mock +->expects( +$this->any() +) +->method('get') +->will($this->throwException()); + +class Test3 +{ + public function method() + { + $mock->expects( + $this->any() + ) + ->method('get') + ->will($this->throwException()); + + $mock->expects($this->any()) + ->method( + 'get' + ) + ->will($this->throwException()); + + $mock + ->expects($this->any()) + ->method( + 'get' + ) + ->will($this->throwException()); + + $mock + ->expects( + $this->any() + ) + ->method('get') + ->will($this->throwException()); + } + + public function method2() + { + $mock->method( + 'param' + )->shouldBeCalled(); + } +} diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed new file mode 100644 index 00000000..dacaa48c --- /dev/null +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed @@ -0,0 +1,400 @@ + $b) { + return 1; + } + + return [ + 1, + 2, + ]; + } +} + +switch (true) { + case '1': + echo 1; + break; + case '2': + echo 2; + break; + default: + switch ($a) { + default: + case 0: + echo 9; + return 17; + case 1: + break; + } + break; +} + +usort($a, function($x, $y) { + return $x > $y; +}); + +function x($a) { + /* + * some comment + */ + $y = $a; + + return $y; +} + +class Test2 { + public $var = <<call($a, $b) + ->another($x) + ->oneMore($d); + +(new DateTime()) + ->modify('-1 day') + ->modify('-1 hour'); + +$m = (new DateTime())->modify('-1 second') + ->modify('+1 second'); + +$val = $class->{$method}($value) + ->{$value}; + +$v = $a->{$m}(1) + ->{$d} + ->date + ->modify('-1 day') + ->format('Y-m-d'); + +$f = function () use ( + $foo, + $bar +) { + return $foo + $bar; +}; + +LABEL: + +$something = 'porter'; + +OTHER: + +$other = 'label'; + +$g = $t->method() + ->another(function () { + $x = 13; + + return $x; + }); + +$concatenation = 'string' + . 'next part'; + +$sum = $a + + $b; + +class B { + public function foo() + { + return function ($stream, $streamIndex) { + return preg_match('#(.*?)\r?\n#', $stream, $matches, null, $streamIndex) === 1 + ? $matches[1] + : substr($stream, $streamIndex); + }; + } + + public function bar($parameters) + { + return array_filter( + $parameters, + function (array $parameter) { + return PHP_VERSION_ID >= 70100 + || (false === strpos($parameter[2], '?') + && ! in_array(strtolower($parameter[2]), ['void', 'iterable'])); + } + ); + } + + public function tar($abc, $def) + { + /* + this part is commented out + and doesn't matter + what + indent +do we have here. + + */ + return PHP_VERSION_ID >= 70100 + && ($abc + || $def); + } + + private function test2($services) + { + return function () use ($services) { + return $services->get('Application') + ->method1() + ->method2(); + }; + } +} + +switch ($a) { + // POST + case 'POST': + $do = 'something'; + break; + // GET + case 'GET': + // my comment here + break; + // All others + default: + $do = 'nothing'; + break; +} + +echo "This is a long +string that spans $numLines lines + without indenting. +"; + +$oldArray = array( + 'it', 'does', + 'not', + 'check', + 'arrays' +); + +class Test3 +{ + public static $a; + + public static function xyz($b) + { + if (static::$a[$b] === null) { + static::$a[$b] = new static( + 'it', + 'is', + 'not checked in that sniff' + ); + } + } +} + +$obj->{$m}( + 'skip', + 'it' +); + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): + if ($bar) $foo = 1; + elseif ($baz) $foo = 2; +endif; + +usort( + $a, + function ( + $x, + $y + ) { + return $x > $y; + } +); + +$var = $foo + && $bar + && ($baz + || $key); + +$num = $multi + * ($val1 + + $val2) + + $int; + +$closure = function ( + $a, + $b, + $c +) { + if ($a + $b > $c) { + return $a + && ($b + || $c); + } + + return $b && ($a + || $c); +}; + +switch ($r) { + case self::TYPE: + $var = null; + if ($x) { + return 1; + } + exit; + case self::GO; + return function () use ($r) { + if ($r) { + throw new \InvalidArgumentException( + sprintf('Error %s', 'value') + ); + } + + return function ($a, $b) { + return $a <=> $b; + }; + }; + case self::DEF: + default: + $var = 1; + throw new \Exception(sprintf( + 'Type "%s" is unknown or cannot be used as property default value.', + get_class($value) + )); +} + +(function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})( + 'a', + 'b' +)( + 'c', + 'd' +); + +(new \DateTime([ + 'something', +]))->format('ymd'); + +$myVariable + ->call(sprintf( + 'Text %s', + 'value' + )); + +class MyClass +{ + public function test() + { + } +} + +$mock->expects( + $this->any() + ) + ->method('get') + ->will($this->throwException()); + +$mock->expects($this->any()) + ->method( + 'get' + ) + ->will($this->throwException()); + +$mock + ->expects($this->any()) + ->method( + 'get' + ) + ->will($this->throwException()); + +$mock + ->expects( + $this->any() + ) + ->method('get') + ->will($this->throwException()); + +class Test3 +{ + public function method() + { + $mock->expects( + $this->any() + ) + ->method('get') + ->will($this->throwException()); + + $mock->expects($this->any()) + ->method( + 'get' + ) + ->will($this->throwException()); + + $mock + ->expects($this->any()) + ->method( + 'get' + ) + ->will($this->throwException()); + + $mock + ->expects( + $this->any() + ) + ->method('get') + ->will($this->throwException()); + } + + public function method2() + { + $mock->method( + 'param' + ) + ->shouldBeCalled(); + } +} diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php new file mode 100644 index 00000000..161def51 --- /dev/null +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php @@ -0,0 +1,137 @@ + 1, + 11 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 16 => 1, + 20 => 1, + 24 => 1, + 25 => 1, + 26 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 35 => 1, + 36 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 43 => 1, + 47 => 1, + 48 => 1, + 49 => 1, + 73 => 1, + 74 => 1, + 77 => 1, + 82 => 1, + 87 => 1, + 91 => 1, + 95 => 1, + 98 => 1, + 101 => 1, + 110 => 1, + 115 => 1, + 119 => 1, + 123 => 1, + 125 => 1, + 129 => 1, + 132 => 1, + 139 => 1, + 150 => 1, + 152 => 1, + 153 => 1, + 168 => 1, + 169 => 1, + 171 => 1, + 178 => 1, + 185 => 1, + 189 => 1, + 191 => 1, + 193 => 1, + 219 => 1, + 220 => 1, + 221 => 1, + 228 => 1, + 233 => 1, + 237 => 1, + 239 => 1, + 244 => 1, + 250 => 1, + 253 => 1, + 260 => 1, + 264 => 1, + 269 => 1, + 279 => 1, + 283 => 1, + 284 => 1, + 285 => 1, + 286 => 1, + 287 => 1, + 288 => 1, + 289 => 1, + 290 => 1, + 291 => 1, + 292 => 1, + 293 => 1, + 294 => 1, + 295 => 1, + 297 => 1, + 298 => 1, + 299 => 1, + 300 => 1, + 301 => 1, + 302 => 1, + 303 => 1, + 304 => 1, + 305 => 1, + 306 => 1, + 307 => 1, + 311 => 1, + 312 => 1, + 313 => 1, + 315 => 1, + 316 => 1, + 318 => 1, + 319 => 1, + 340 => 1, + 341 => 1, + 342 => 1, + 346 => 1, + 347 => 1, + 348 => 1, + 352 => 1, + 354 => 1, + 359 => 1, + 360 => 1, + 361 => 1, + 370 => 1, + 371 => 1, + 372 => 1, + 376 => 1, + 377 => 1, + 378 => 1, + 399 => 1, + 400 => 2, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From 835987558199617cc4b5113d7b153aa279eb2286 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sat, 15 Jul 2017 10:23:17 +0200 Subject: [PATCH 114/225] ScopeIndent sniff checks also indents in arrays --- .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 48 ++++++++++++------- .../Sniffs/WhiteSpace/ScopeIndentUnitTest.inc | 21 ++++++-- .../WhiteSpace/ScopeIndentUnitTest.inc.fixed | 23 +++++++-- .../Sniffs/WhiteSpace/ScopeIndentUnitTest.php | 17 +++++++ 4 files changed, 84 insertions(+), 25 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index c92c9519..9e31af6d 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -38,6 +38,7 @@ class ScopeIndentSniff implements Sniff T_GOTO_LABEL, T_COMMA, T_OPEN_PARENTHESIS, + T_OPEN_SHORT_ARRAY, ]; private $caseEndToken = [ @@ -62,6 +63,8 @@ public function __construct() T_SEMICOLON => T_SEMICOLON, T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_OPEN_SHORT_ARRAY => T_OPEN_SHORT_ARRAY, + T_ARRAY => T_ARRAY, T_COMMA => T_COMMA, T_INLINE_ELSE => T_INLINE_ELSE, T_INLINE_THEN => T_INLINE_THEN, @@ -77,6 +80,7 @@ public function __construct() T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS, T_USE => T_USE, T_CLOSURE => T_CLOSURE, + T_ARRAY => T_ARRAY, ]; } @@ -186,18 +190,6 @@ public function process(File $phpcsFile, $stackPtr) continue; } - // skip short arrays - if ($tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) { - $i = $tokens[$i]['bracket_closer']; - continue; - } - - // skip long arrays - if ($tokens[$i]['code'] === T_ARRAY) { - $i = $tokens[$i]['parenthesis_closer']; - continue; - } - // skip heredoc/nowdoc if ($tokens[$i]['code'] === T_START_HEREDOC || $tokens[$i]['code'] === T_START_NOWDOC @@ -295,7 +287,7 @@ public function process(File $phpcsFile, $stackPtr) $extras[$endOfStatement] = $this->indent; } - $extraIndent += $this->indent;// expectedIndent += $this->indent; + $extraIndent += $this->indent; } elseif ($tokens[$next]['code'] === T_CLOSE_PARENTHESIS) { if (isset($extras[$next])) { $extraIndent -= $extras[$next]; @@ -336,6 +328,11 @@ public function process(File $phpcsFile, $stackPtr) continue; } + } elseif ($tokens[$next]['code'] === T_CLOSE_SHORT_ARRAY) { + if (isset($extras[$next])) { + $extraIndent -= $extras[$next]; + unset($extras[$next]); + } } elseif ($tokens[$next]['code'] === T_OBJECT_OPERATOR) { if (isset($extras[$next])) { $extraIndent -= $extras[$next]; @@ -448,12 +445,23 @@ public function process(File $phpcsFile, $stackPtr) // count extra indent $ei = 0; if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS + || $tokens[$i]['code'] === T_OPEN_SHORT_ARRAY || ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET && isset($tokens[$i]['scope_closer'])) ) { - $xEnd = $tokens[$i]['code'] === T_OPEN_PARENTHESIS - ? $tokens[$i]['parenthesis_closer'] - : $tokens[$i]['scope_closer']; + switch ($tokens[$i]['code']) { + case T_OPEN_PARENTHESIS: + $key = 'parenthesis_closer'; + break; + case T_OPEN_SHORT_ARRAY: + $key = 'bracket_closer'; + break; + default: + $key = 'scope_closer'; + break; + + } + $xEnd = $tokens[$i][$key]; // no extra indent if closing parenthesis/bracket is in the same line if ($tokens[$i]['line'] === $tokens[$xEnd]['line']) { @@ -462,12 +470,16 @@ public function process(File $phpcsFile, $stackPtr) // if there is another open bracket in that line, skip current one. $another = $i; - while (($another = $phpcsFile->findNext([T_OPEN_PARENTHESIS, T_OPEN_CURLY_BRACKET], $another + 1)) + $openTags = [T_OPEN_PARENTHESIS, T_OPEN_SHORT_ARRAY, T_OPEN_CURLY_BRACKET]; + while (($another = $phpcsFile->findNext($openTags, $another + 1)) && $tokens[$another]['line'] === $tokens[$i]['line'] ) { if (($tokens[$another]['code'] === T_OPEN_PARENTHESIS && $tokens[$tokens[$another]['parenthesis_closer']]['line'] > $tokens[$another]['line']) - || (isset($tokens[$another]['scope_closer']) + || ($tokens[$another]['code'] === T_OPEN_SHORT_ARRAY + && $tokens[$tokens[$another]['bracket_closer']]['line'] > $tokens[$another]['line']) + || ($tokens[$another]['code'] === T_OPEN_CURLY_BRACKET + && isset($tokens[$another]['scope_closer']) && $tokens[$tokens[$another]['scope_closer']]['line'] > $tokens[$another]['line']) ) { continue 2; diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc index fc382a26..56cbe2b3 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc @@ -202,9 +202,9 @@ string that spans $numLines lines "; $oldArray = array( - 'it', 'does', - 'not', - 'check', + 'the', 'sniff', + 'does', + 'check', 'indents', 'in', 'arrays' ); @@ -399,4 +399,19 @@ class Test3 'param' )->shouldBeCalled(); } + +public function method3() +{ +$list = [ +'fn' => function ($a) { +if ($a === true) { +echo 'hi'; +} +}, +'call' => sprintf( +'Text %s', +'param' +), +]; +} } diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed index dacaa48c..8bb38bed 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed @@ -199,10 +199,10 @@ string that spans $numLines lines "; $oldArray = array( - 'it', 'does', - 'not', - 'check', - 'arrays' + 'the', 'sniff', + 'does', + 'check', 'indents', 'in', + 'arrays' ); class Test3 @@ -397,4 +397,19 @@ class Test3 ) ->shouldBeCalled(); } + + public function method3() + { + $list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + }, + 'call' => sprintf( + 'Text %s', + 'param' + ), + ]; + } } diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php index 161def51..505342f9 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php @@ -63,6 +63,9 @@ public function getErrorList($testFile = '') 189 => 1, 191 => 1, 193 => 1, + 205 => 1, + 207 => 1, + 208 => 1, 219 => 1, 220 => 1, 221 => 1, @@ -127,6 +130,20 @@ public function getErrorList($testFile = '') 378 => 1, 399 => 1, 400 => 2, + 403 => 1, + 404 => 1, + 405 => 1, + 406 => 1, + 407 => 1, + 408 => 1, + 409 => 1, + 410 => 1, + 411 => 1, + 412 => 1, + 413 => 1, + 414 => 1, + 415 => 1, + 416 => 1, ]; } From d16680f15726ce38fdf27d15f476e82cc957fa03 Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 24 Jul 2017 12:05:21 +0200 Subject: [PATCH 115/225] Updated to PHP_CodeSniffer 3.0.2 --- composer.json | 10 ++++---- composer.lock | 66 +++++++++++++++++++++++++-------------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/composer.json b/composer.json index e801eebc..258b035e 100644 --- a/composer.json +++ b/composer.json @@ -7,10 +7,10 @@ "coding standard" ], "require": { - "squizlabs/php_codesniffer": "3.0.1" + "squizlabs/php_codesniffer": "3.0.2" }, "require-dev": { - "phpunit/phpunit": "^6.2.2 || ^5.7.20" + "phpunit/phpunit": "^5.7.21 || ^6.2.3" }, "autoload": { "psr-4": { @@ -31,10 +31,10 @@ "@cs-check", "@test" ], - "upload-coverage": "coveralls -v", "cs-check": "phpcs", "cs-fix": "phpcbf", - "test": "phpunit", - "test-coverage": "phpunit --coverage-clover clover.xml" + "test": "phpunit --colors=always", + "test-coverage": "phpunit --colors=always --coverage-clover clover.xml", + "upload-coverage": "coveralls -v" } } diff --git a/composer.lock b/composer.lock index ba8d1b80..b061ffb8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "43689fb0f5f9c3fd5f5d35801f93357b", + "content-hash": "33702ceeea4be9b4e4871c51859ce754", "packages": [ { "name": "squizlabs/php_codesniffer", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "f9eaf037edf22fdfccf04cb0ab57ebcb1e166219" + "reference": "c7594a88ae75401e8f8d0bd4deb8431b39045c51" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/f9eaf037edf22fdfccf04cb0ab57ebcb1e166219", - "reference": "f9eaf037edf22fdfccf04cb0ab57ebcb1e166219", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/c7594a88ae75401e8f8d0bd4deb8431b39045c51", + "reference": "c7594a88ae75401e8f8d0bd4deb8431b39045c51", "shasum": "" }, "require": { @@ -55,7 +55,7 @@ "phpcs", "standards" ], - "time": "2017-06-14T01:23:49+00:00" + "time": "2017-07-18T01:12:32+00:00" } ], "packages-dev": [ @@ -211,22 +211,22 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "3.1.1", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" + "reference": "46f7e8bb075036c92695b15a1ddb6971c751e585" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/46f7e8bb075036c92695b15a1ddb6971c751e585", + "reference": "46f7e8bb075036c92695b15a1ddb6971c751e585", "shasum": "" }, "require": { "php": ">=5.5", "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.2.0", + "phpdocumentor/type-resolver": "^0.4.0", "webmozart/assert": "^1.0" }, "require-dev": { @@ -252,24 +252,24 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-09-30T07:12:33+00:00" + "time": "2017-07-15T11:38:20+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.2.1", + "version": "0.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", "shasum": "" }, "require": { - "php": ">=5.5", + "php": "^5.5 || ^7.0", "phpdocumentor/reflection-common": "^1.0" }, "require-dev": { @@ -299,7 +299,7 @@ "email": "me@mikevanriel.com" } ], - "time": "2016-11-25T06:54:22+00:00" + "time": "2017-07-14T14:27:02+00:00" }, { "name": "phpspec/prophecy", @@ -615,16 +615,16 @@ }, { "name": "phpunit/phpunit", - "version": "5.7.20", + "version": "5.7.21", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "3cb94a5f8c07a03c8b7527ed7468a2926203f58b" + "reference": "3b91adfb64264ddec5a2dee9851f354aa66327db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3cb94a5f8c07a03c8b7527ed7468a2926203f58b", - "reference": "3cb94a5f8c07a03c8b7527ed7468a2926203f58b", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3b91adfb64264ddec5a2dee9851f354aa66327db", + "reference": "3b91adfb64264ddec5a2dee9851f354aa66327db", "shasum": "" }, "require": { @@ -693,20 +693,20 @@ "testing", "xunit" ], - "time": "2017-05-22T07:42:55+00:00" + "time": "2017-06-21T08:11:54+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.4.3", + "version": "3.4.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24" + "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", - "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", + "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", "shasum": "" }, "require": { @@ -752,7 +752,7 @@ "mock", "xunit" ], - "time": "2016-12-08T20:27:08+00:00" + "time": "2017-06-30T09:13:00+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -1269,16 +1269,16 @@ }, { "name": "symfony/yaml", - "version": "v3.3.2", + "version": "v3.3.5", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "9752a30000a8ca9f4b34b5227d15d0101b96b063" + "reference": "1f93a8d19b8241617f5074a123e282575b821df8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/9752a30000a8ca9f4b34b5227d15d0101b96b063", - "reference": "9752a30000a8ca9f4b34b5227d15d0101b96b063", + "url": "https://api.github.com/repos/symfony/yaml/zipball/1f93a8d19b8241617f5074a123e282575b821df8", + "reference": "1f93a8d19b8241617f5074a123e282575b821df8", "shasum": "" }, "require": { @@ -1320,7 +1320,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-06-02T22:05:06+00:00" + "time": "2017-06-15T12:58:50+00:00" }, { "name": "webmozart/assert", From 2c6cf8c2ecc7b76c588d66d823226a991e5a212b Mon Sep 17 00:00:00 2001 From: webimpress Date: Sat, 29 Jul 2017 08:41:32 +0200 Subject: [PATCH 116/225] Fix wrong token name --- src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index 9e31af6d..513b97a1 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -76,7 +76,7 @@ public function __construct() T_SELF => T_SELF, T_STATIC => T_STATIC, T_VARIABLE => T_VARIABLE, - T_CLOSE_CURLY_BRACKET => T_CLOSE_PARENTHESIS, + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS, T_USE => T_USE, T_CLOSURE => T_CLOSURE, From 52b435c714879609262aa36b004c4075cd967acc Mon Sep 17 00:00:00 2001 From: webimpress Date: Sat, 29 Jul 2017 09:45:37 +0200 Subject: [PATCH 117/225] ScopeIndent sniff - fixed indent of closing bracket/parenthesis --- .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 29 ++++++++++--------- .../Sniffs/WhiteSpace/ScopeIndentUnitTest.inc | 23 +++++++++++++++ .../WhiteSpace/ScopeIndentUnitTest.inc.fixed | 23 +++++++++++++++ .../Sniffs/WhiteSpace/ScopeIndentUnitTest.php | 15 ++++++++++ 4 files changed, 77 insertions(+), 13 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index 513b97a1..c348bebb 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -443,7 +443,6 @@ public function process(File $phpcsFile, $stackPtr) } // count extra indent - $ei = 0; if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS || $tokens[$i]['code'] === T_OPEN_SHORT_ARRAY || ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET @@ -459,7 +458,6 @@ public function process(File $phpcsFile, $stackPtr) default: $key = 'scope_closer'; break; - } $xEnd = $tokens[$i][$key]; @@ -495,14 +493,21 @@ public function process(File $phpcsFile, $stackPtr) ++$firstInNextLine; } + // Additional indent of the content if it should be one more depth. + $ei1 = 0; if ($tokens[$first]['level'] === $tokens[$firstInNextLine]['level'] && $tokens[$firstInNextLine]['code'] !== T_CLOSE_CURLY_BRACKET ) { - $ei += $this->indent; + $ei1 = $this->indent; + if (isset($extras[$xEnd])) { + $extras[$xEnd] += $ei1; + } else { + $extras[$xEnd] = $ei1; + } } + $ei2 = 0; $next = $phpcsFile->findNext(Tokens::$emptyTokens, $i + 1, null, true); - if ($tokens[$next]['line'] > $tokens[$i]['line']) { // current line indent $whitespace = $phpcsFile->findFirstOnLine([], $i, true); @@ -512,19 +517,17 @@ public function process(File $phpcsFile, $stackPtr) - $extraIndent; if ($sum > 0) { - $ei += $sum; + $ei2 = $sum; + if (isset($extras[$xEnd + 1])) { + $extras[$xEnd + 1] += $ei2; + } else { + $extras[$xEnd + 1] = $ei2; + } } } } - } - if ($ei) { - $extraIndent += $ei; - if (isset($extras[$xEnd])) { - $extras[$xEnd] += $ei; - } else { - $extras[$xEnd] = $ei; - } + $extraIndent += $ei1 + $ei2; } } diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc index 56cbe2b3..3ac5cbe2 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc @@ -415,3 +415,26 @@ echo 'hi'; ]; } } + +$foo = $bar ++ [ +'foo', +'bar', +]; + +$foo = $bar ++ func( +'foo', +'bar' +); + +$f->foo( +'foo' +) +->bar( +'bar', +$foo ++ [ +'bar', +] +); diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed index 8bb38bed..27bd0e19 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed @@ -413,3 +413,26 @@ class Test3 ]; } } + +$foo = $bar + + [ + 'foo', + 'bar', + ]; + +$foo = $bar + + func( + 'foo', + 'bar' + ); + +$f->foo( + 'foo' + ) + ->bar( + 'bar', + $foo + + [ + 'bar', + ] + ); diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php index 505342f9..5315b907 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php @@ -144,6 +144,21 @@ public function getErrorList($testFile = '') 414 => 1, 415 => 1, 416 => 1, + 420 => 1, + 421 => 1, + 422 => 1, + 426 => 1, + 427 => 1, + 428 => 1, + 432 => 1, + 433 => 1, + 434 => 1, + 435 => 1, + 436 => 1, + 437 => 1, + 438 => 1, + 439 => 1, + 440 => 1, ]; } From 2854410fd757f8776e9006dd5cbda05094ef3dfe Mon Sep 17 00:00:00 2001 From: webimpress Date: Sat, 29 Jul 2017 13:07:45 +0200 Subject: [PATCH 118/225] Removed cases from Arrays/Format sniff covered by ScopeIndent sniff --- .../Sniffs/Arrays/FormatSniff.php | 38 ------------- test/Sniffs/Arrays/FormatUnitTest.inc.fixed | 56 +++++++++---------- test/Sniffs/Arrays/FormatUnitTest.php | 17 ++---- .../Sniffs/WhiteSpace/ScopeIndentUnitTest.inc | 11 ++++ .../WhiteSpace/ScopeIndentUnitTest.inc.fixed | 11 ++++ .../Sniffs/WhiteSpace/ScopeIndentUnitTest.php | 6 ++ 6 files changed, 60 insertions(+), 79 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index acd841bd..318a3684 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -122,33 +122,6 @@ private function multiLineArray(File $phpcsFile, $stackPtr) $phpcsFile->fixer->replaceToken($firstOnLine - 1, ''); } } - - $expected = $indent + $this->indent; - - // Check array element indent. - if ($firstOnLine = $phpcsFile->findFirstOnLine(T_WHITESPACE, $next)) { - $found = strlen($tokens[$firstOnLine]['content']); - if ($found !== $expected) { - $error = 'Invalid array element indent - expected %d spaces; %d found'; - $data = [ - $expected, - $found, - ]; - $fix = $phpcsFile->addFixableError($error, $firstOnLine, 'ElementIndent', $data); - - if ($fix) { - $phpcsFile->fixer->replaceToken($firstOnLine, str_repeat(' ', $expected)); - } - } - } else { - $error = 'Invalid array element indent - expected %d spaces; 0 found'; - $data = [$expected]; - $fix = $phpcsFile->addFixableError($error, $next, 'ElementIndent', $data); - - if ($fix) { - $phpcsFile->fixer->addContentBefore($next, str_repeat(' ', $expected)); - } - } } if ($tokens[$next]['code'] === T_COMMENT @@ -180,17 +153,6 @@ private function multiLineArray(File $phpcsFile, $stackPtr) $phpcsFile->fixer->addNewlineBefore($bracketCloser); $phpcsFile->fixer->endChangeset(); } - } elseif ($first === $bracketCloser - 1 - && $tokens[$first]['code'] === T_WHITESPACE - && strlen($tokens[$first]['content']) !== $indent - ) { - $error = 'Expected %d spaces; found %d'; - $data = [$indent, strlen($tokens[$first]['content'])]; - $fix = $phpcsFile->addFixableError($error, $first, 'CloseBracketIndent', $data); - - if ($fix) { - $phpcsFile->fixer->replaceToken($first, str_repeat(' ', $indent)); - } } } } diff --git a/test/Sniffs/Arrays/FormatUnitTest.inc.fixed b/test/Sniffs/Arrays/FormatUnitTest.inc.fixed index dabb47a4..aa8fb246 100644 --- a/test/Sniffs/Arrays/FormatUnitTest.inc.fixed +++ b/test/Sniffs/Arrays/FormatUnitTest.inc.fixed @@ -1,25 +1,25 @@ 1, - 2 => 1, - 3 => 2, - 4 => 3, + 1 => 1, +2 => 1, + 3 => 2, +4 => 3, 5 => 5, ]; $arr = [ 'elem', - 'elem', +'elem', ]; $a = array_merge([ ['a' => 'b'], ['c' => 'd'], -]); + ]); diff --git a/test/Sniffs/Arrays/FormatUnitTest.php b/test/Sniffs/Arrays/FormatUnitTest.php index 63c4f5bd..6c82d0fd 100644 --- a/test/Sniffs/Arrays/FormatUnitTest.php +++ b/test/Sniffs/Arrays/FormatUnitTest.php @@ -9,14 +9,7 @@ public function getErrorList() { return [ 2 => 2, - 4 => 1, - 5 => 1, - // 6 => 1, - 7 => 1, - 11 => 1, - // 12 => 1, 14 => 2, - 15 => 1, 16 => 2, 19 => 1, 20 => 1, @@ -24,22 +17,20 @@ public function getErrorList() 25 => 1, 31 => 3, 33 => 1, - 38 => 2, + 38 => 1, 39 => 1, - 40 => 1, 47 => 2, 49 => 1, 53 => 2, 55 => 1, - 56 => 2, + 56 => 1, 62 => 2, 63 => 1, - 68 => 2, - 69 => 2, + 68 => 1, + 69 => 1, 74 => 1, 75 => 1, 76 => 1, - 82 => 1, ]; } diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc index 3ac5cbe2..2683ef17 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc @@ -438,3 +438,14 @@ $foo 'bar', ] ); + +$this->abc($a, [ + 'param1', + 'param2', +]) + ->def(); + +$this->def($a, [ + 'abc', + 'def', + ]); diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed index 27bd0e19..bc5dd41c 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed @@ -436,3 +436,14 @@ $f->foo( 'bar', ] ); + +$this->abc($a, [ + 'param1', + 'param2', + ]) + ->def(); + +$this->def($a, [ + 'abc', + 'def', +]); diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php index 5315b907..8f75cce6 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php @@ -159,6 +159,12 @@ public function getErrorList($testFile = '') 438 => 1, 439 => 1, 440 => 1, + 443 => 1, + 444 => 1, + 445 => 1, + 449 => 1, + 450 => 1, + 451 => 1, ]; } From f806a777fb492add6651d905ab3c8d928a12886e Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 8 Aug 2017 09:14:48 +0200 Subject: [PATCH 119/225] Removed sniff ControlStructures/MultilineBrace in favor of ScopeIndent sniff All tests moved to ScopeIndent sniff tests. Added more cases. This sniff now check very strictly indents in code including code inside parenthesis of control structures. In some cases we have got some false-positive errors (caused by wrongly formated code), but they are correctly fixed with auto fixer. --- .../ControlStructures/MultilineBraceSniff.php | 290 ----------------- .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 308 ++++++++++++++++-- .../MultilineBraceUnitTest.php | 44 --- .../ScopeIndentUnitTest.1.inc} | 76 +++++ .../ScopeIndentUnitTest.1.inc.fixed} | 80 ++++- .../Sniffs/WhiteSpace/ScopeIndentUnitTest.inc | 28 ++ .../WhiteSpace/ScopeIndentUnitTest.inc.fixed | 28 ++ .../Sniffs/WhiteSpace/ScopeIndentUnitTest.php | 86 ++++- 8 files changed, 570 insertions(+), 370 deletions(-) delete mode 100644 src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php delete mode 100644 test/Sniffs/ControlStructures/MultilineBraceUnitTest.php rename test/Sniffs/{ControlStructures/MultilineBraceUnitTest.inc => WhiteSpace/ScopeIndentUnitTest.1.inc} (60%) rename test/Sniffs/{ControlStructures/MultilineBraceUnitTest.inc.fixed => WhiteSpace/ScopeIndentUnitTest.1.inc.fixed} (60%) diff --git a/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php b/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php deleted file mode 100644 index 2e9e6aca..00000000 --- a/src/ZendCodingStandard/Sniffs/ControlStructures/MultilineBraceSniff.php +++ /dev/null @@ -1,290 +0,0 @@ -getTokens(); - - $opener = $tokens[$stackPtr]; - if (! isset($opener['scope_condition'])) { - return; - } - - $scopeCondition = $tokens[$opener['scope_condition']]; - - if ($scopeCondition['line'] === $opener['line']) { - return; - } - - if (in_array($scopeCondition['code'], $this->skipStructures, true)) { - return; - } - - $parenthesis = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); - if ($tokens[$parenthesis]['code'] !== T_CLOSE_PARENTHESIS) { - return; - } - - $prev = $phpcsFile->findPrevious( - Tokens::$emptyTokens + [T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS], - $parenthesis - 1, - null, - true - ); - if ($scopeCondition['line'] === $tokens[$prev]['line']) { - $error = 'Closing parenthesis must be in the same line as control structure.'; - $fix = $phpcsFile->addFixableError($error, $parenthesis, 'UnnecessaryLineBreak'); - - if ($fix) { - $phpcsFile->fixer->beginChangeset(); - for ($i = $prev + 1; $i < $parenthesis; ++$i) { - if ($tokens[$i]['code'] === T_WHITESPACE) { - $phpcsFile->fixer->replaceToken($i, ''); - } - } - $phpcsFile->fixer->endChangeset(); - } - - return; - } - - $token = $tokens[$parenthesis]['parenthesis_opener']; - while ($token = $phpcsFile->findNext(T_CLOSE_PARENTHESIS, $token + 1, $parenthesis)) { - $prevCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, $token - 1, null, true); - if ($tokens[$prevCloser]['line'] === $tokens[$token]['line']) { - continue; - } - - $open = $tokens[$token]['parenthesis_opener']; - $prevOpener = $phpcsFile->findPrevious(Tokens::$emptyTokens, $open - 1, null, true); - $first = $phpcsFile->findFirstOnLine([], $open, true); - - if (in_array($tokens[$prevOpener]['code'], $this->functionCall, true)) { - // It is a function call. - if ($tokens[$open]['line'] < $tokens[$token]['line'] - && $tokens[$token - 1]['line'] < $tokens[$token]['line'] - && $tokens[$first]['code'] === T_WHITESPACE - ) { - $expectedIndentWidth = strlen($tokens[$first]['content']); - $error = 'Multi-line function closing parenthesis not indented correctly;' - . ' expected %d spaces but found 0'; - $data = [ - $expectedIndentWidth, - ]; - $fix = $phpcsFile->addFixableError($error, $token, 'ClosingParenthesisMultiLineFunction', $data); - - if ($fix) { - $phpcsFile->fixer->addContentBefore($token, str_repeat(' ', $expectedIndentWidth)); - } - } - } else { - $error = 'Invalid closing parenthesis position.'; - $fix = $phpcsFile->addFixableError($error, $token, 'InvalidClosingParenthesisPosition'); - - if ($fix) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->addContent($prevCloser, $tokens[$token]['content']); - $phpcsFile->fixer->replaceToken($token, ''); - $t = $token + 1; - while ($tokens[$t]['code'] === T_WHITESPACE - && $tokens[$t]['line'] === $tokens[$token]['line'] - ) { - $phpcsFile->fixer->replaceToken($t, ''); - - ++$t; - } - $phpcsFile->fixer->endChangeset(); - } - } - } - - $prev = $parenthesis; - $squashClose = false; - while (($prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $prev - 1, null, true)) - && $tokens[$prev]['code'] === T_CLOSE_PARENTHESIS - && $tokens[$prev]['line'] > $scopeCondition['line'] - && $tokens[$tokens[$prev]['parenthesis_opener']]['line'] === $scopeCondition['line'] - && ! $phpcsFile->findFirstOnLine( - Tokens::$emptyTokens + [T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS], - $prev, - true - ) - ) { - if ($tokens[$prev]['line'] <= $tokens[$parenthesis]['line'] - 1) { - $error = 'Invalid closing parenthesis position.'; - $fix = $phpcsFile->addFixableError($error, $prev, 'InvalidClosingParenthesisPosition'); - - if ($fix) { - $phpcsFile->fixer->beginChangeset(); - for ($i = $prev + 1; $i < $parenthesis; ++$i) { - if ($tokens[$i]['code'] === T_WHITESPACE) { - $phpcsFile->fixer->replaceToken($i, ''); - } - } - $phpcsFile->fixer->endChangeset(); - } - } elseif ($tokens[$prev + 1]['code'] === T_WHITESPACE) { - $error = 'Unexpected whitespace before closing parenthesis.'; - $fix = $phpcsFile->addFixableError($error, $prev + 1, 'UnexpectedSpacesBeforeClosingParenthesis'); - - if ($fix) { - $phpcsFile->fixer->replaceToken($prev + 1, ''); - } - } - - $squashClose = true; - } - - // Find indent before control structure - $indent = ''; - $firstOnLine = $phpcsFile->findFirstOnLine([], $opener['scope_condition'], true); - if ($tokens[$firstOnLine]['code'] === T_WHITESPACE) { - $indent = $tokens[$firstOnLine]['content']; - } - - if (! $squashClose) { - if ($tokens[$prev]['line'] <= $tokens[$parenthesis]['line'] - 1) { - // Check indent - $whitespace = $phpcsFile->findFirstOnLine(T_WHITESPACE, $parenthesis); - if ($whitespace && $tokens[$whitespace]['content'] !== $indent) { - // Invalid indent before parenthesis - $error = 'Invalid indent before closing parenthesis.'; - $fix = $phpcsFile->addFixableError($error, $whitespace, 'InvalidIndentBeforeParenthesis'); - - if ($fix) { - $phpcsFile->fixer->replaceToken($whitespace, $indent); - } - } elseif (! $whitespace && $indent) { - // Missing indent before closing parenthesis - $error = 'Missing indent before closing parenthesis.'; - $fix = $phpcsFile->addFixableError($error, $parenthesis, 'MissingIndentBeforeParenthesis'); - - if ($fix) { - $phpcsFile->fixer->addContentBefore($parenthesis, $indent); - } - } - } else { - // Needed new line before parenthesis - $error = 'Closing parentheses must be in new line.'; - $fix = $phpcsFile->addFixableError($error, $parenthesis, 'NewLine'); - - if ($fix) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->addContentBefore($parenthesis, $indent); - $phpcsFile->fixer->addNewlineBefore($parenthesis); - $phpcsFile->fixer->endChangeset(); - } - } - } - - // Check indent of each line - $line = $scopeCondition['line']; - $token = $opener['scope_condition']; - $depth = 0; - do { - while ($tokens[$token]['line'] === $line) { - if ($tokens[$token]['code'] === T_OPEN_PARENTHESIS) { - $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $token - 1, null, true); - if (in_array($tokens[$prev]['code'], $this->functionCall, true)) { - $token = $tokens[$token]['parenthesis_closer'] + 1; - $line = $tokens[$token]['line']; - continue; - } - ++$depth; - } elseif ($tokens[$token]['code'] === T_CLOSE_PARENTHESIS) { - --$depth; - } - - ++$token; - } - $line = $tokens[$token]['line']; - - if ($line >= $opener['line']) { - break; - } - - $first = $phpcsFile->findNext(Tokens::$emptyTokens, $token, null, true); - if ($tokens[$first]['code'] === T_CLOSE_PARENTHESIS) { - continue; - } elseif (in_array( - $tokens[$first]['code'], - Tokens::$comparisonTokens + [T_INSTANCEOF => T_INSTANCEOF], - true - )) { - $expectedIndentWidth = strlen($indent) + ($depth + 1) * $this->indent; - } else { - $expectedIndentWidth = strlen($indent) + $depth * $this->indent; - } - - if ($tokens[$token]['code'] === T_WHITESPACE) { - $indentWidth = strlen($tokens[$token]['content']); - - if ($indentWidth !== $expectedIndentWidth) { - $error = 'Invalid indent. Expected %d spaces, found %d'; - $data = [ - $expectedIndentWidth, - $indentWidth, - ]; - $fix = $phpcsFile->addFixableError($error, $token, 'InvalidIndent', $data); - - if ($fix) { - $phpcsFile->fixer->replaceToken($token, str_repeat(' ', $expectedIndentWidth)); - } - } - } else { - // Missing indent - $error = 'Missing line indent. Expected %d spaces, found 0'; - $data = [$expectedIndentWidth]; - $fix = $phpcsFile->addFixableError($error, $token, 'MissingIndent', $data); - - if ($fix) { - $phpcsFile->fixer->addContentBefore($token, str_repeat(' ', $expectedIndentWidth)); - } - } - } while ($line < $opener['line']); - } -} diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index c348bebb..239ea7d2 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -24,9 +24,11 @@ class ScopeIndentSniff implements Sniff private $controlStructures = [ T_IF => T_IF, T_ELSEIF => T_ELSEIF, + T_SWITCH => T_SWITCH, T_WHILE => T_WHILE, T_FOR => T_FOR, T_FOREACH => T_FOREACH, + T_CATCH => T_CATCH, ]; private $endOfStatement = [ @@ -72,6 +74,7 @@ public function __construct() ]; $this->functionToken = Tokens::$functionNameTokens + + $this->controlStructures + [ T_SELF => T_SELF, T_STATIC => T_STATIC, @@ -198,22 +201,120 @@ public function process(File $phpcsFile, $stackPtr) continue; } - if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) { - if (empty($tokens[$i]['parenthesis_owner'])) { - $parenthesisOwner = $phpcsFile->findPrevious(Tokens::$emptyTokens, $i - 1, null, true); - } else { - $parenthesisOwner = $tokens[$i]['parenthesis_owner']; - } + if (isset($extras[$i])) { + $extraIndent -= $extras[$i]; + unset($extras[$i]); + } - if (in_array($tokens[$parenthesisOwner]['code'], $this->controlStructures, true)) { - $i = $tokens[$i]['parenthesis_closer']; - continue; + // check if closing parenthesis is in the same line as control structure + if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET + && isset($tokens[$i]['scope_condition']) + && ($scopeCondition = $tokens[$tokens[$i]['scope_condition']]) + && ! in_array($scopeCondition['code'], [T_FUNCTION, T_CLOSURE], true) + && ($parenthesis = $phpcsFile->findPrevious(Tokens::$emptyTokens, $i - 1, null, true)) + && $tokens[$parenthesis]['code'] === T_CLOSE_PARENTHESIS + && $tokens[$parenthesis]['line'] > $scopeCondition['line'] + ) { + $prev = $phpcsFile->findPrevious( + Tokens::$emptyTokens + [T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS], + $parenthesis - 1, + null, + true + ); + if ($scopeCondition['line'] === $tokens[$prev]['line']) { + $error = 'Closing parenthesis must be in the same line as control structure.'; + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'UnnecessaryLineBreak'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($j = $prev + 1; $j < $parenthesis; ++$j) { + if ($tokens[$j]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($j, ''); + } + } + $phpcsFile->fixer->endChangeset(); + } } } - if (isset($extras[$i])) { - $extraIndent -= $extras[$i]; - unset($extras[$i]); + // closing parenthesis in next line when multi-line control structure + if ($tokens[$i]['code'] === T_CLOSE_PARENTHESIS + && $tokens[$i]['line'] > $tokens[$tokens[$i]['parenthesis_opener']]['line'] + ) { + $prev = $phpcsFile->findPrevious( + Tokens::$emptyTokens + + [ + T_CLOSE_SHORT_ARRAY => T_CLOSE_SHORT_ARRAY, + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS, + ], + $i - 1, + null, + true + ); + + $owner = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + $tokens[$i]['parenthesis_opener'] - 1, + null, + true + ); + if ($tokens[$prev]['line'] === $tokens[$i]['line'] + && in_array($tokens[$owner]['code'], $this->functionToken, true) + && $this->hasContainNewLine( + $phpcsFile, + $tokens[$i]['parenthesis_opener'], + $tokens[$i]['parenthesis_closer'] + ) + ) { + $error = 'Closing parenthesis must be in next line'; + $fix = $phpcsFile->addFixableError($error, $i, 'ClosingParenthesis'); + + if ($fix) { + $phpcsFile->fixer->addNewlineBefore($i); + } + } + + if (isset($tokens[$owner]['scope_condition'])) { + $scopeCondition = $tokens[$owner]; + $prev = $i; + while (($prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $prev - 1, null, true)) + && $tokens[$prev]['code'] === T_CLOSE_PARENTHESIS + && $tokens[$prev]['line'] > $scopeCondition['line'] + && $tokens[$tokens[$prev]['parenthesis_opener']]['line'] === $scopeCondition['line'] + && ! $phpcsFile->findFirstOnLine( + Tokens::$emptyTokens + [T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS], + $prev, + true + ) + ) { + if ($tokens[$prev]['line'] <= $tokens[$i]['line'] - 1) { + $error = 'Invalid closing parenthesis position.'; + $fix = $phpcsFile->addFixableError($error, $prev, 'InvalidClosingParenthesisPosition'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($j = $prev + 1; $j < $i; ++$j) { + if ($tokens[$j]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($j, ''); + } + } + $phpcsFile->fixer->endChangeset(); + } + } elseif ($tokens[$prev + 1]['code'] === T_WHITESPACE) { + $error = 'Unexpected whitespace before closing parenthesis.'; + $fix = $phpcsFile->addFixableError( + $error, + $prev + 1, + 'UnexpectedSpacesBeforeClosingParenthesis' + ); + + if ($fix) { + $phpcsFile->fixer->replaceToken($prev + 1, ''); + } + } + } + } } if ($tokens[$i]['code'] === T_OBJECT_OPERATOR) { @@ -298,6 +399,7 @@ public function process(File $phpcsFile, $stackPtr) $owner = $phpcsFile->findPrevious(Tokens::$emptyTokens, $opener - 1, null, true); // if it is not a function call + // and not a control structure if (! in_array($tokens[$owner]['code'], $this->functionToken, true)) { $error = 'Closing parenthesis must be in previous line.'; $fix = $phpcsFile->addFixableError($error, $next, 'ClosingParenthesis'); @@ -387,11 +489,54 @@ public function process(File $phpcsFile, $stackPtr) } elseif (! in_array($tokens[$prev]['code'], $this->endOfStatement, true) && $tokens[$next]['code'] !== T_OPEN_CURLY_BRACKET ) { - if ($expectedIndent + $extraIndent <= $previousIndent) { + if ($this->getControlStructurePtr($phpcsFile, $next) !== false) { + $addIndent = $expectedIndent + $extraIndent - $this->indent <= $previousIndent + && ! in_array($tokens[$next]['code'], Tokens::$booleanOperators, true); + } else { + $addIndent = $expectedIndent + $extraIndent <= $previousIndent; + } + + if ($addIndent) { $expectedIndent = ($depth + 1) * $this->indent; } } + // one less indent + // if it is in control structure + // and there is no eol between + // open and close parenthesis + if (($tokens[$next]['code'] === T_CLOSE_PARENTHESIS + || $tokens[$next]['code'] === T_CLOSE_SHORT_ARRAY + || ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET + && isset($tokens[$next]['scope_opener']))) + && ($controlStructurePtr = $this->getControlStructurePtr($phpcsFile, $next)) + && $tokens[$next]['line'] < $tokens[$tokens[$controlStructurePtr]['parenthesis_closer']]['line'] + && ! $this->hasContainNewLine( + $phpcsFile, + $tokens[$controlStructurePtr]['parenthesis_opener'], + $tokens[$controlStructurePtr]['parenthesis_closer'] + ) + ) { + // if it is closure, so $next token is T_CLOSE_PARENTHESIS + // and the following non-empty token is T_CURLY_OPEN_BRACKET + // then expect one more indent on the whole body of the closure. + if ($tokens[$next]['code'] === T_CLOSE_PARENTHESIS + && ($fNext = $phpcsFile->findNext(Tokens::$emptyTokens, $next + 1, null, true)) + && $tokens[$fNext]['code'] === T_OPEN_CURLY_BRACKET + && isset($tokens[$fNext]['scope_closer']) + ) { + $extraIndent -= $this->indent; + $sc = $tokens[$fNext]['scope_closer']; + if (isset($extras[$sc])) { + $extras[$sc] -= $this->indent; + } else { + $extras[$sc] = - $this->indent; + } + } else { + $expectedIndent -= $this->indent; + } + } + $expectedIndent += $extraIndent; $previousIndent = $expectedIndent; @@ -466,19 +611,46 @@ public function process(File $phpcsFile, $stackPtr) continue; } - // if there is another open bracket in that line, skip current one. + // If open parenthesis belongs to control structure + if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS + && isset($tokens[$i]['parenthesis_owner']) + && in_array($tokens[$tokens[$i]['parenthesis_owner']]['code'], $this->controlStructures, true) + ) { + // search for first non-empty token in line, + // where is the closing parenthesis of the control structure + $firstOnLine = $phpcsFile->findFirstOnLine(Tokens::$emptyTokens, $xEnd, true); + + $extraIndent += $this->indent; + if (isset($extras[$firstOnLine])) { + $extras[$firstOnLine] += $this->indent; + } else { + $extras[$firstOnLine] = $this->indent; + } + + $controlStructure[$tokens[$i]['line']] = $tokens[$i]['parenthesis_closer']; + + continue; + } + + // If there is another open bracket in the current line, + // and closing bracket is in the same line as closing bracket of the current token + // (or there is no no line break between them) + // skip the current token to count indent. $another = $i; $openTags = [T_OPEN_PARENTHESIS, T_OPEN_SHORT_ARRAY, T_OPEN_CURLY_BRACKET]; while (($another = $phpcsFile->findNext($openTags, $another + 1)) && $tokens[$another]['line'] === $tokens[$i]['line'] ) { if (($tokens[$another]['code'] === T_OPEN_PARENTHESIS - && $tokens[$tokens[$another]['parenthesis_closer']]['line'] > $tokens[$another]['line']) + && $tokens[$tokens[$another]['parenthesis_closer']]['line'] > $tokens[$another]['line'] + && ! $this->hasContainNewLine($phpcsFile, $tokens[$another]['parenthesis_closer'], $xEnd)) || ($tokens[$another]['code'] === T_OPEN_SHORT_ARRAY - && $tokens[$tokens[$another]['bracket_closer']]['line'] > $tokens[$another]['line']) + && $tokens[$tokens[$another]['bracket_closer']]['line'] > $tokens[$another]['line'] + && ! $this->hasContainNewLine($phpcsFile, $tokens[$another]['bracket_closer'], $xEnd)) || ($tokens[$another]['code'] === T_OPEN_CURLY_BRACKET && isset($tokens[$another]['scope_closer']) - && $tokens[$tokens[$another]['scope_closer']]['line'] > $tokens[$another]['line']) + && $tokens[$tokens[$another]['scope_closer']]['line'] > $tokens[$another]['line'] + && ! $this->hasContainNewLine($phpcsFile, $tokens[$another]['scope_closer'], $xEnd)) ) { continue 2; } @@ -494,15 +666,27 @@ public function process(File $phpcsFile, $stackPtr) } // Additional indent of the content if it should be one more depth. + // We count them only if it is not in the same line as control structure + // or the closing parenthesis of the statement is not in the line with + // closing parenthesis of control structure. $ei1 = 0; - if ($tokens[$first]['level'] === $tokens[$firstInNextLine]['level'] - && $tokens[$firstInNextLine]['code'] !== T_CLOSE_CURLY_BRACKET + $controlStructurePtr = $this->getControlStructurePtr($phpcsFile, $i); + if ($controlStructurePtr === false + || $this->hasContainNewLine( + $phpcsFile, + $tokens[$controlStructurePtr]['parenthesis_opener'], + $tokens[$controlStructurePtr]['parenthesis_closer'] + ) ) { - $ei1 = $this->indent; - if (isset($extras[$xEnd])) { - $extras[$xEnd] += $ei1; - } else { - $extras[$xEnd] = $ei1; + if ($tokens[$first]['level'] === $tokens[$firstInNextLine]['level'] + && $tokens[$firstInNextLine]['code'] !== T_CLOSE_CURLY_BRACKET + ) { + $ei1 = $this->indent; + if (isset($extras[$xEnd])) { + $extras[$xEnd] += $ei1; + } else { + $extras[$xEnd] = $ei1; + } } } @@ -535,6 +719,8 @@ public function process(File $phpcsFile, $stackPtr) } /** + * @todo: need name refactor and method description + * * @param File $phpcsFile * @param int $ptr * @return int|null @@ -561,6 +747,8 @@ private function fp(File $phpcsFile, $ptr) } /** + * @todo: need name refactor and method description + * * @param File $phpcsFile * @param int $ptr * @return int|null @@ -585,6 +773,9 @@ private function np(File $phpcsFile, $ptr) } /** + * Checks if there is another object operator + * before $ptr token. + * * @param File $phpcsFile * @param int $ptr * @return int|null @@ -607,4 +798,73 @@ private function hasPrevObjectOperator(File $phpcsFile, $ptr) return null; } + + /** + * Checks if between $fromPtr and $toPtr is any new line + * excluding scopes (arrays, closures, multiline function calls). + * + * @param File $phpcsFile + * @param int $fromPtr + * @param int $toPtr + * @return bool + */ + private function hasContainNewLine(File $phpcsFile, $fromPtr, $toPtr) + { + $tokens = $phpcsFile->getTokens(); + + for ($j = $fromPtr + 1; $j < $toPtr; ++$j) { + switch ($tokens[$j]['code']) { + case T_OPEN_PARENTHESIS: + case T_ARRAY: + $j = $tokens[$j]['parenthesis_closer']; + continue 2; + case T_OPEN_CURLY_BRACKET: + if (isset($tokens[$j]['scope_closer'])) { + $j = $tokens[$j]['scope_closer']; + } + continue 2; + case T_OPEN_SHORT_ARRAY: + $j = $tokens[$j]['bracket_closer']; + continue 2; + case T_WHITESPACE: + if (strpos($tokens[$j]['content'], $phpcsFile->eolChar) !== false) { + return true; + } + } + } + + return false; + } + + /** + * Checks if the $ptr token is inside control structure + * and returns the control structure pointer; + * otherwise returns boolean `false`. + * + * @param File $phpcsFile + * @param int $ptr + * @return int|false + */ + private function getControlStructurePtr(File $phpcsFile, $ptr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$ptr]['nested_parenthesis'])) { + foreach ($tokens[$ptr]['nested_parenthesis'] as $start => $end) { + // find expression before + $prev = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + $start - 1, + null, + true + ); + + if (in_array($tokens[$prev]['code'], $this->controlStructures, true)) { + return $prev; + } + } + } + + return false; + } } diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php b/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php deleted file mode 100644 index 040d23d6..00000000 --- a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.php +++ /dev/null @@ -1,44 +0,0 @@ - 1, - 34 => 1, - 38 => 1, - 41 => 1, - 42 => 1, - 45 => 1, - 48 => 1, - 56 => 1, - 61 => 1, - 62 => 1, - 63 => 1, - 74 => 1, - 81 => 1, - 87 => 1, - 89 => 1, - 97 => 1, - 98 => 1, - 106 => 1, - 111 => 1, - 116 => 1, - 117 => 1, - 128 => 1, - 136 => 1, - 138 => 1, - 146 => 1, - 149 => 1, - ]; - } - - public function getWarningList($testFile = '') - { - return []; - } -} diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.1.inc similarity index 60% rename from test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc rename to test/Sniffs/WhiteSpace/ScopeIndentUnitTest.1.inc index 7b9eb166..de2e3388 100644 --- a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.1.inc @@ -150,3 +150,79 @@ if ($a ) { echo 3; } + +while (in_array($a, [ + $b, + $c, + $d, +], true)) { +} + +if (in_array($a, array( + $b, + $c +), true)) { +} elseif (myFunc($a, anotherFunc( + $d, + $e +), true)) { +} + +do { +} while (myFunc($a, function ( + $b, + $c +) { + return $b <=> $c; +}, true)); + +if (myFunc([ + 'elem1', + 'elem2', +], function ( + $a, + $b +) { + return $a > $b; +}, [ + 'param' => 'val' +])) { +} elseif (($a + && $b) + || ($c + && $d) + || ($e + && $f + && $g) +) { +} + +do { +} while ($a + && ($b + || $c + || $d) +); + +if ($a + && (($b + || $c + || $d) + && $e + || ($f && $g)) +) { +} elseif ($a + && ((($b + || $c + || $d) + && $e) + || ($f && $g)) +) { +} elseif ($a + && (($x && ($b + || $c + || $d) + && $e) + || ($f && $g)) +) { +} diff --git a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed similarity index 60% rename from test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed rename to test/Sniffs/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed index e09367f1..429cc2b0 100644 --- a/test/Sniffs/ControlStructures/MultilineBraceUnitTest.inc.fixed +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed @@ -64,8 +64,8 @@ if ($a && ($b || $c) && preg_match( - '/a/', - 'b' + '/a/', + 'b' ) ) { return 12; @@ -144,3 +144,79 @@ if ($a ) { echo 3; } + +while (in_array($a, [ + $b, + $c, + $d, +], true)) { +} + +if (in_array($a, array( + $b, + $c +), true)) { +} elseif (myFunc($a, anotherFunc( + $d, + $e +), true)) { +} + +do { +} while (myFunc($a, function ( + $b, + $c +) { + return $b <=> $c; +}, true)); + +if (myFunc([ + 'elem1', + 'elem2', +], function ( + $a, + $b +) { + return $a > $b; +}, [ + 'param' => 'val' +])) { +} elseif (($a + && $b) + || ($c + && $d) + || ($e + && $f + && $g) +) { +} + +do { +} while ($a + && ($b + || $c + || $d) +); + +if ($a + && (($b + || $c + || $d) + && $e + || ($f && $g)) +) { +} elseif ($a + && ((($b + || $c + || $d) + && $e) + || ($f && $g)) +) { +} elseif ($a + && (($x && ($b + || $c + || $d) + && $e) + || ($f && $g)) +) { +} diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc index 2683ef17..d6f1a8ac 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc @@ -414,6 +414,26 @@ echo 'hi'; ), ]; } + +public function method4() +{ +$this->console +->writeln( +Argument::that(function ($arg) { +if (false === strpos($arg, 'src/ErrorMiddleware.php')) { +return false; +} +if (false === strpos( +$arg, +sprintf('implementing %s', ErrorMiddlewareInterface::class) +)) { +return false; +} +return true; +}) +) +->shouldBeCalled(); +} } $foo = $bar @@ -449,3 +469,11 @@ $this->def($a, [ 'abc', 'def', ]); + +throw new MyException(sprintf( +'Type "%s" is unknown or cannot be used as property default value.', +get_class($value) +), $param, [ +'foo' => 'bar', +'bar' => 'baz', +]); diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed index bc5dd41c..be31a841 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed @@ -412,6 +412,26 @@ class Test3 ), ]; } + + public function method4() + { + $this->console + ->writeln( + Argument::that(function ($arg) { + if (false === strpos($arg, 'src/ErrorMiddleware.php')) { + return false; + } + if (false === strpos( + $arg, + sprintf('implementing %s', ErrorMiddlewareInterface::class) + )) { + return false; + } + return true; + }) + ) + ->shouldBeCalled(); + } } $foo = $bar @@ -447,3 +467,11 @@ $this->def($a, [ 'abc', 'def', ]); + +throw new MyException(sprintf( + 'Type "%s" is unknown or cannot be used as property default value.', + get_class($value) +), $param, [ + 'foo' => 'bar', + 'bar' => 'baz', +]); diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php index 8f75cce6..490713a0 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php @@ -7,6 +7,50 @@ class ScopeIndentUnitTest extends TestCase { public function getErrorList($testFile = '') { + if ($testFile === 'ScopeIndentUnitTest.1.inc') { + return [ + 24 => 1, + 34 => 2, + 38 => 1, + 39 => 1, // + 40 => 1, // + 41 => 1, + 42 => 1, + 45 => 2, + 46 => 1, // + 47 => 1, // + 48 => 2, + 49 => 1, // + 50 => 1, // + 56 => 1, + 61 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 1, + 72 => 1, // + 73 => 1, // + 74 => 2, // 1 + 80 => 1, // + 81 => 2, // 1 + 87 => 1, + 89 => 1, + 95 => 1, // + 96 => 1, // + 97 => 2, // 1 + 98 => 2, // 1 + 106 => 1, + 111 => 2, // 1 -- todo: the same errors + 117 => 1, + 128 => 1, + 136 => 1, + 138 => 1, + 146 => 1, + 149 => 1, + ]; + } + return [ 10 => 1, 11 => 1, @@ -144,27 +188,49 @@ public function getErrorList($testFile = '') 414 => 1, 415 => 1, 416 => 1, + 418 => 1, + 419 => 1, 420 => 1, 421 => 1, 422 => 1, + 423 => 1, + 424 => 1, + 425 => 1, 426 => 1, 427 => 1, 428 => 1, + 429 => 1, + 430 => 1, + 431 => 1, 432 => 1, 433 => 1, 434 => 1, - 435 => 1, 436 => 1, - 437 => 1, - 438 => 1, - 439 => 1, 440 => 1, - 443 => 1, - 444 => 1, - 445 => 1, - 449 => 1, - 450 => 1, - 451 => 1, + 441 => 1, + 442 => 1, + 446 => 1, + 447 => 1, + 448 => 1, + 452 => 1, + 453 => 1, + 454 => 1, + 455 => 1, + 456 => 1, + 457 => 1, + 458 => 1, + 459 => 1, + 460 => 1, + 463 => 1, + 464 => 1, + 465 => 1, + 469 => 1, + 470 => 1, + 471 => 1, + 474 => 1, + 475 => 1, + 477 => 1, + 478 => 1, ]; } From 4af30539d0dc6feedd9fb309802f3b3a9a9313e5 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 8 Aug 2017 09:15:09 +0200 Subject: [PATCH 120/225] CS fix - detected by ScopeIndent sniff --- src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php index 661bad67..88ac2c7f 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php @@ -225,8 +225,7 @@ public function process(File $phpcsFile, $stackPtr) } while ($nextUse !== false && (! CodingStandard::isTraitUse($phpcsFile, $nextUse) || ! isset($tokens[$nextUse]['conditions'][$class]) - || $tokens[$nextUse]['level'] !== $tokens[$class]['level'] + 1 - ) + || $tokens[$nextUse]['level'] !== $tokens[$class]['level'] + 1) ); if ($nextUse !== false) { From ec950b55d70de01615eaf25c931aef937a1f7861 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 8 Aug 2017 11:02:03 +0200 Subject: [PATCH 121/225] ReturnType sniff is now configurable It is possible to set number of spaces: - before colon - after colon - after nullable op --- .../Sniffs/Formatting/ReturnTypeSniff.php | 90 ++++++++++++++----- .../Formatting/ReturnTypeUnitTest.1.inc | 22 +++++ .../Formatting/ReturnTypeUnitTest.1.inc.fixed | 18 ++++ test/Sniffs/Formatting/ReturnTypeUnitTest.inc | 3 + .../Formatting/ReturnTypeUnitTest.inc.fixed | 3 + test/Sniffs/Formatting/ReturnTypeUnitTest.php | 70 +++++++++------ 6 files changed, 155 insertions(+), 51 deletions(-) create mode 100644 test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc create mode 100644 test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc.fixed diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php index 208b0741..d4443111 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php @@ -6,11 +6,27 @@ use PHP_CodeSniffer\Util\Tokens; use function in_array; +use function str_repeat; use function strtolower; use function trim; class ReturnTypeSniff implements Sniff { + /** + * @var int + */ + public $spacesBeforeColon = 0; + + /** + * @var int + */ + public $spacesAfterColon = 1; + + /** + * @var int + */ + public $spacesAfterNullable = 0; + /** * @var string[] */ @@ -41,53 +57,81 @@ public function register() */ public function process(File $phpcsFile, $stackPtr) { + $this->spacesBeforeColon = (int) $this->spacesBeforeColon; + $this->spacesAfterColon = (int) $this->spacesAfterColon; + $this->spacesAfterNullable = (int) $this->spacesAfterNullable; $tokens = $phpcsFile->getTokens(); $colon = $phpcsFile->findPrevious(T_COLON, $stackPtr - 1); - // No space before colon. - if ($tokens[$colon - 1]['code'] !== T_CLOSE_PARENTHESIS) { - $error = 'There must be no space before colon.'; - $fix = $phpcsFile->addFixableError($error, $colon - 1, 'SpaceBeforeColon'); + // Token before colon does not match configured number of spaces. + if (($this->spacesBeforeColon === 0 + && $tokens[$colon - 1]['code'] !== T_CLOSE_PARENTHESIS) + || ($this->spacesBeforeColon > 0 + && ($tokens[$colon - 1]['code'] !== T_WHITESPACE + || $tokens[$colon - 1]['content'] !== str_repeat(' ', $this->spacesBeforeColon))) + ) { + $error = 'There must be exactly %d space(s) between the closing parenthesis and the colon' + . ' when declaring a return type for a function'; + $data = [$this->spacesBeforeColon]; + $fix = $phpcsFile->addFixableError($error, $colon - 1, 'SpaceBeforeColon', $data); if ($fix) { $phpcsFile->fixer->beginChangeset(); $token = $colon - 1; - do { + while ($tokens[$token]['code'] !== T_CLOSE_PARENTHESIS) { $phpcsFile->fixer->replaceToken($token, ''); --$token; - } while ($tokens[$token]['code'] !== T_CLOSE_PARENTHESIS); + } + if ($this->spacesBeforeColon > 0) { + $phpcsFile->fixer->addContentBefore($colon, str_repeat(' ', $this->spacesBeforeColon)); + } $phpcsFile->fixer->endChangeset(); } } - // Only one space after colon. - if ($tokens[$colon + 1]['code'] !== T_WHITESPACE) { - $error = 'There must be one space after colon and before return type declaration.'; - $fix = $phpcsFile->addFixableError($error, $colon, 'NoSpaceAfterColon'); - - if ($fix) { - $phpcsFile->fixer->addContent($colon, ' '); - } - } elseif ($tokens[$colon + 1]['content'] !== ' ') { - $error = 'There must be only one space after colon and before return type declaration.'; - $fix = $phpcsFile->addFixableError($error, $colon + 1, 'TooManySpacesAfterColon'); + // Token after colon does not match configured number of spaces. + if (($this->spacesAfterColon === 0 + && $tokens[$colon + 1]['code'] === T_WHITESPACE) + || ($this->spacesAfterColon > 0 + && ($tokens[$colon + 1]['code'] !== T_WHITESPACE + || $tokens[$colon + 1]['content'] !== str_repeat(' ', $this->spacesAfterColon))) + ) { + $error = 'There must be exactly %d space(s) between the colon and return type' + . ' when declaring a return type for a function'; + $data = [$this->spacesAfterColon]; + $fix = $phpcsFile->addFixableError($error, $colon, 'NoSpaceAfterColon', $data); if ($fix) { - $phpcsFile->fixer->replaceToken($colon + 1, ' '); + if ($tokens[$colon + 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($colon + 1, str_repeat(' ', $this->spacesAfterColon)); + } else { + $phpcsFile->fixer->addContent($colon, ' '); + } } } $nullable = $phpcsFile->findNext(T_NULLABLE, $colon + 1, $stackPtr); if ($nullable) { - // Check if there is space after nullable operator. - if ($tokens[$nullable + 1]['code'] === T_WHITESPACE) { - $error = 'Space is not not allowed after nullable operator.'; - $fix = $phpcsFile->addFixableError($error, $nullable + 1, 'SpaceAfterNullable'); + // Token after nullable does not match configured number of spaces. + if (($this->spacesAfterNullable === 0 + && $tokens[$nullable + 1]['code'] === T_WHITESPACE) + || ($this->spacesAfterNullable > 0 + && ($tokens[$nullable + 1]['code'] !== T_WHITESPACE + || $tokens[$nullable + 1]['content'] !== str_repeat(' ', $this->spacesAfterNullable))) + ) { + $error = 'There must be exactly %d space(s) between the nullable operator and return type' + . ' when declaring a return type for a function'; + $data = [$this->spacesAfterNullable]; + $fix = $phpcsFile->addFixableError($error, $nullable + 1, 'SpaceAfterNullable', $data); if ($fix) { - $phpcsFile->fixer->replaceToken($nullable + 1, ''); + if ($tokens[$nullable + 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($nullable + 1, ''); + } else { + $phpcsFile->fixer->addContent($nullable, str_repeat(' ', $this->spacesAfterNullable)); + } } } } diff --git a/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc b/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc new file mode 100644 index 00000000..57487440 --- /dev/null +++ b/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc @@ -0,0 +1,22 @@ + 1, + 7 => 3, + 9 => 2, + 10 => 2, + 17 => 2, + 18 => 3, + 20 => 1, + 21 => 2, + 22 => 1, + ]; + } + return [ - 5 => 1, - 9 => 1, - 27 => 2, - 36 => 1, - 42 => 2, - 50 => 2, - 55 => 2, - 56 => 2, - 57 => 2, - 58 => 3, - 59 => 3, + 8 => 1, + 12 => 1, + 30 => 2, + 39 => 1, + 45 => 2, + 53 => 2, + 58 => 2, + 59 => 2, 60 => 2, - 61 => 1, - 62 => 2, - 63 => 1, - 64 => 2, - 65 => 1, - 66 => 2, - 67 => 1, - 68 => 2, - 69 => 1, - 70 => 2, - 71 => 1, - 72 => 2, - 73 => 1, - 74 => 2, - 75 => 1, + 61 => 3, + 62 => 3, + 63 => 2, + 64 => 1, + 65 => 2, + 66 => 1, + 67 => 2, + 68 => 1, + 69 => 2, + 70 => 1, + 71 => 2, + 72 => 1, + 73 => 2, + 74 => 1, + 75 => 2, + 76 => 1, 77 => 2, 78 => 1, - 80 => 1, - 81 => 3, + 80 => 2, + 81 => 1, + 83 => 1, + 84 => 3, ]; } From 7ba3a9f93fbc437b9d6cab8639b3f84c49914673 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 8 Aug 2017 11:02:38 +0200 Subject: [PATCH 122/225] ReturnType sniff: removed "double" and added "object" from simple return type list --- src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php | 2 +- test/Sniffs/Formatting/ReturnTypeUnitTest.inc | 4 ++-- test/Sniffs/Formatting/ReturnTypeUnitTest.inc.fixed | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php index d4443111..d5131168 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php @@ -34,7 +34,7 @@ class ReturnTypeSniff implements Sniff 'void', 'int', 'float', - 'double', + 'object', 'string', 'array', 'iterable', diff --git a/test/Sniffs/Formatting/ReturnTypeUnitTest.inc b/test/Sniffs/Formatting/ReturnTypeUnitTest.inc index 55209cb6..14cf1974 100644 --- a/test/Sniffs/Formatting/ReturnTypeUnitTest.inc +++ b/test/Sniffs/Formatting/ReturnTypeUnitTest.inc @@ -60,8 +60,8 @@ interface MyInterface public function c() :?int; public function d() :Float; public function e() :? float; - public function f():Double; - public function g():?double; + public function f():Object; + public function g():?object; public function h():Array; public function i() : ?array; public function j():String; diff --git a/test/Sniffs/Formatting/ReturnTypeUnitTest.inc.fixed b/test/Sniffs/Formatting/ReturnTypeUnitTest.inc.fixed index 7526c3f6..9e07af3f 100644 --- a/test/Sniffs/Formatting/ReturnTypeUnitTest.inc.fixed +++ b/test/Sniffs/Formatting/ReturnTypeUnitTest.inc.fixed @@ -58,8 +58,8 @@ interface MyInterface public function c(): ?int; public function d(): float; public function e(): ?float; - public function f(): double; - public function g(): ?double; + public function f(): object; + public function g(): ?object; public function h(): array; public function i(): ?array; public function j(): string; From 4666cd629dc3ad68f5e96f322c5b9211a9c576ca Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 8 Aug 2017 11:22:18 +0200 Subject: [PATCH 123/225] ReturnType sniff refactor and fix of removing non-whitespace tokens --- .../Sniffs/Formatting/ReturnTypeSniff.php | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php index d5131168..ad5fa567 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php @@ -64,12 +64,13 @@ public function process(File $phpcsFile, $stackPtr) $colon = $phpcsFile->findPrevious(T_COLON, $stackPtr - 1); + $expected = str_repeat(' ', $this->spacesBeforeColon); // Token before colon does not match configured number of spaces. if (($this->spacesBeforeColon === 0 - && $tokens[$colon - 1]['code'] !== T_CLOSE_PARENTHESIS) + && $tokens[$colon - 1]['code'] === T_WHITESPACE) || ($this->spacesBeforeColon > 0 && ($tokens[$colon - 1]['code'] !== T_WHITESPACE - || $tokens[$colon - 1]['content'] !== str_repeat(' ', $this->spacesBeforeColon))) + || $tokens[$colon - 1]['content'] !== $expected)) ) { $error = 'There must be exactly %d space(s) between the closing parenthesis and the colon' . ' when declaring a return type for a function'; @@ -78,25 +79,25 @@ public function process(File $phpcsFile, $stackPtr) if ($fix) { $phpcsFile->fixer->beginChangeset(); - $token = $colon - 1; - while ($tokens[$token]['code'] !== T_CLOSE_PARENTHESIS) { - $phpcsFile->fixer->replaceToken($token, ''); - - --$token; - } - if ($this->spacesBeforeColon > 0) { - $phpcsFile->fixer->addContentBefore($colon, str_repeat(' ', $this->spacesBeforeColon)); + if ($tokens[$colon - 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($colon - 1, $expected); + if (isset($tokens[$colon - 2]) && $tokens[$colon - 2]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($colon - 2, ''); + } + } else { + $phpcsFile->fixer->addContentBefore($colon, $expected); } $phpcsFile->fixer->endChangeset(); } } + $expected = str_repeat(' ', $this->spacesAfterColon); // Token after colon does not match configured number of spaces. if (($this->spacesAfterColon === 0 && $tokens[$colon + 1]['code'] === T_WHITESPACE) || ($this->spacesAfterColon > 0 && ($tokens[$colon + 1]['code'] !== T_WHITESPACE - || $tokens[$colon + 1]['content'] !== str_repeat(' ', $this->spacesAfterColon))) + || $tokens[$colon + 1]['content'] !== $expected)) ) { $error = 'There must be exactly %d space(s) between the colon and return type' . ' when declaring a return type for a function'; @@ -105,21 +106,22 @@ public function process(File $phpcsFile, $stackPtr) if ($fix) { if ($tokens[$colon + 1]['code'] === T_WHITESPACE) { - $phpcsFile->fixer->replaceToken($colon + 1, str_repeat(' ', $this->spacesAfterColon)); + $phpcsFile->fixer->replaceToken($colon + 1, $expected); } else { - $phpcsFile->fixer->addContent($colon, ' '); + $phpcsFile->fixer->addContent($colon, $expected); } } } $nullable = $phpcsFile->findNext(T_NULLABLE, $colon + 1, $stackPtr); if ($nullable) { + $expected = str_repeat(' ', $this->spacesAfterNullable); // Token after nullable does not match configured number of spaces. if (($this->spacesAfterNullable === 0 && $tokens[$nullable + 1]['code'] === T_WHITESPACE) || ($this->spacesAfterNullable > 0 && ($tokens[$nullable + 1]['code'] !== T_WHITESPACE - || $tokens[$nullable + 1]['content'] !== str_repeat(' ', $this->spacesAfterNullable))) + || $tokens[$nullable + 1]['content'] !== $expected)) ) { $error = 'There must be exactly %d space(s) between the nullable operator and return type' . ' when declaring a return type for a function'; @@ -128,9 +130,9 @@ public function process(File $phpcsFile, $stackPtr) if ($fix) { if ($tokens[$nullable + 1]['code'] === T_WHITESPACE) { - $phpcsFile->fixer->replaceToken($nullable + 1, ''); + $phpcsFile->fixer->replaceToken($nullable + 1, $expected); } else { - $phpcsFile->fixer->addContent($nullable, str_repeat(' ', $this->spacesAfterNullable)); + $phpcsFile->fixer->addContent($nullable, $expected); } } } From 5ea427b3fdd82ffab7d17bd60f2d529d01fd4606 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 8 Aug 2017 12:54:44 +0200 Subject: [PATCH 124/225] ReturnType sniff refactor --- .../Sniffs/Formatting/ReturnTypeSniff.php | 232 ++++++++++++------ .../Formatting/ReturnTypeUnitTest.1.inc | 2 +- .../Formatting/ReturnTypeUnitTest.1.inc.fixed | 2 +- 3 files changed, 160 insertions(+), 76 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php index ad5fa567..ca40d195 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php @@ -62,94 +62,48 @@ public function process(File $phpcsFile, $stackPtr) $this->spacesAfterNullable = (int) $this->spacesAfterNullable; $tokens = $phpcsFile->getTokens(); - $colon = $phpcsFile->findPrevious(T_COLON, $stackPtr - 1); - - $expected = str_repeat(' ', $this->spacesBeforeColon); - // Token before colon does not match configured number of spaces. - if (($this->spacesBeforeColon === 0 - && $tokens[$colon - 1]['code'] === T_WHITESPACE) - || ($this->spacesBeforeColon > 0 - && ($tokens[$colon - 1]['code'] !== T_WHITESPACE - || $tokens[$colon - 1]['content'] !== $expected)) - ) { - $error = 'There must be exactly %d space(s) between the closing parenthesis and the colon' - . ' when declaring a return type for a function'; - $data = [$this->spacesBeforeColon]; - $fix = $phpcsFile->addFixableError($error, $colon - 1, 'SpaceBeforeColon', $data); - - if ($fix) { - $phpcsFile->fixer->beginChangeset(); - if ($tokens[$colon - 1]['code'] === T_WHITESPACE) { - $phpcsFile->fixer->replaceToken($colon - 1, $expected); - if (isset($tokens[$colon - 2]) && $tokens[$colon - 2]['code'] === T_WHITESPACE) { - $phpcsFile->fixer->replaceToken($colon - 2, ''); - } - } else { - $phpcsFile->fixer->addContentBefore($colon, $expected); - } - $phpcsFile->fixer->endChangeset(); - } - } - - $expected = str_repeat(' ', $this->spacesAfterColon); - // Token after colon does not match configured number of spaces. - if (($this->spacesAfterColon === 0 - && $tokens[$colon + 1]['code'] === T_WHITESPACE) - || ($this->spacesAfterColon > 0 - && ($tokens[$colon + 1]['code'] !== T_WHITESPACE - || $tokens[$colon + 1]['content'] !== $expected)) - ) { - $error = 'There must be exactly %d space(s) between the colon and return type' - . ' when declaring a return type for a function'; - $data = [$this->spacesAfterColon]; - $fix = $phpcsFile->addFixableError($error, $colon, 'NoSpaceAfterColon', $data); + // Check if between the closing parenthesis and return type are only allowed tokens. + $parenthesisCloser = $phpcsFile->findPrevious( + [ + T_COLON, + T_NS_SEPARATOR, + T_NULLABLE, + T_STRING, + T_WHITESPACE, + ], + $stackPtr - 1, + null, + true + ); + if ($tokens[$parenthesisCloser]['code'] !== T_CLOSE_PARENTHESIS) { + $error = 'Return type declaration contains invalid token %s'; + $data = [$tokens[$parenthesisCloser]['type']]; + $phpcsFile->addError($error, $parenthesisCloser, 'InvalidToken', $data); - if ($fix) { - if ($tokens[$colon + 1]['code'] === T_WHITESPACE) { - $phpcsFile->fixer->replaceToken($colon + 1, $expected); - } else { - $phpcsFile->fixer->addContent($colon, $expected); - } - } + return; } + $colon = $phpcsFile->findPrevious(T_COLON, $stackPtr - 1); $nullable = $phpcsFile->findNext(T_NULLABLE, $colon + 1, $stackPtr); + + $this->checkSpacesBeforeColon($phpcsFile, $colon); + $this->checkSpacesAfterColon($phpcsFile, $colon); if ($nullable) { - $expected = str_repeat(' ', $this->spacesAfterNullable); - // Token after nullable does not match configured number of spaces. - if (($this->spacesAfterNullable === 0 - && $tokens[$nullable + 1]['code'] === T_WHITESPACE) - || ($this->spacesAfterNullable > 0 - && ($tokens[$nullable + 1]['code'] !== T_WHITESPACE - || $tokens[$nullable + 1]['content'] !== $expected)) - ) { - $error = 'There must be exactly %d space(s) between the nullable operator and return type' - . ' when declaring a return type for a function'; - $data = [$this->spacesAfterNullable]; - $fix = $phpcsFile->addFixableError($error, $nullable + 1, 'SpaceAfterNullable', $data); - - if ($fix) { - if ($tokens[$nullable + 1]['code'] === T_WHITESPACE) { - $phpcsFile->fixer->replaceToken($nullable + 1, $expected); - } else { - $phpcsFile->fixer->addContent($nullable, $expected); - } - } - } + $this->checkSpacesAfterNullable($phpcsFile, $nullable); } $first = $phpcsFile->findNext(Tokens::$emptyTokens, ($nullable ?: $colon) + 1, null, true); $end = $phpcsFile->findNext([T_SEMICOLON, T_OPEN_CURLY_BRACKET], $stackPtr + 1); $last = $phpcsFile->findPrevious(Tokens::$emptyTokens, $end - 1, null, true); - $invalid = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR, T_RETURN_TYPE], $first, $last + 1, true); - if ($invalid) { + $space = $phpcsFile->findNext(T_WHITESPACE, $first, $last + 1); + if ($space) { $error = 'Return type declaration contains invalid token %s'; - $data = [$tokens[$invalid]['type']]; - $fix = $phpcsFile->addFixableError($error, $invalid, 'InvalidToken', $data); + $data = [$tokens[$space]['type']]; + $fix = $phpcsFile->addFixableError($error, $space, 'SpaceInReturnType', $data); if ($fix) { - $phpcsFile->fixer->replaceToken($invalid, ''); + $phpcsFile->fixer->replaceToken($space, ''); } return; @@ -173,4 +127,134 @@ public function process(File $phpcsFile, $stackPtr) } } } + + /** + * Check if token before colon match configured number of spaces. + * + * @param File $phpcsFile + * @param int $colon + * @return void + */ + private function checkSpacesBeforeColon(File $phpcsFile, $colon) + { + $tokens = $phpcsFile->getTokens(); + + // The whitespace before colon is not expected and it is not present. + if ($this->spacesBeforeColon === 0 + && $tokens[$colon - 1]['code'] !== T_WHITESPACE + ) { + return; + } + + $expected = str_repeat(' ', $this->spacesBeforeColon); + + // Previous token contains expected number of spaces, + // and before whitespace there is close parenthesis token. + if ($this->spacesBeforeColon > 0 + && $tokens[$colon - 1]['content'] === $expected + && $tokens[$colon - 2]['code'] === T_CLOSE_PARENTHESIS + ) { + return; + } + + $error = 'There must be exactly %d space(s) between the closing parenthesis and the colon' + . ' when declaring a return type for a function'; + $data = [$this->spacesBeforeColon]; + $fix = $phpcsFile->addFixableError($error, $colon - 1, 'SpacesBeforeColon', $data); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + if ($tokens[$colon - 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($colon - 1, $expected); + if (isset($tokens[$colon - 2]) && $tokens[$colon - 2]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($colon - 2, ''); + } + } else { + $phpcsFile->fixer->addContentBefore($colon, $expected); + } + $phpcsFile->fixer->endChangeset(); + } + } + + /** + * Check if token after colon match configured number of spaces. + * + * @param File $phpcsFile + * @param int $colon + * @return void + */ + private function checkSpacesAfterColon(File $phpcsFile, $colon) + { + $tokens = $phpcsFile->getTokens(); + + // The whitespace after colon is not expected and it is not present. + if ($this->spacesAfterColon === 0 + && $tokens[$colon + 1]['code'] !== T_WHITESPACE + ) { + return; + } + + $expected = str_repeat(' ', $this->spacesAfterColon); + + // Next token contains expected number of spaces. + if ($this->spacesAfterColon > 0 + && $tokens[$colon + 1]['content'] === $expected + ) { + return; + } + + $error = 'There must be exactly %d space(s) between the colon and return type' + . ' when declaring a return type for a function'; + $data = [$this->spacesAfterColon]; + $fix = $phpcsFile->addFixableError($error, $colon, 'SpacesAfterColon', $data); + + if ($fix) { + if ($tokens[$colon + 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($colon + 1, $expected); + } else { + $phpcsFile->fixer->addContent($colon, $expected); + } + } + } + + /** + * Checks if token after nullable operator match configured number of spaces. + * + * @param File $phpcsFile + * @param int $nullable + * @return void + */ + private function checkSpacesAfterNullable(File $phpcsFile, $nullable) + { + $tokens = $phpcsFile->getTokens(); + + // The whitespace after nullable operator is not expected and it is not present. + if ($this->spacesAfterNullable === 0 + && $tokens[$nullable + 1]['code'] !== T_WHITESPACE + ) { + return; + } + + $expected = str_repeat(' ', $this->spacesAfterNullable); + + // Next token contains expected number of spaces. + if ($this->spacesAfterNullable > 0 + && $tokens[$nullable + 1]['content'] === $expected + ) { + return; + } + + $error = 'There must be exactly %d space(s) between the nullable operator and return type' + . ' when declaring a return type for a function'; + $data = [$this->spacesAfterNullable]; + $fix = $phpcsFile->addFixableError($error, $nullable + 1, 'SpacesAfterNullable', $data); + + if ($fix) { + if ($tokens[$nullable + 1]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($nullable + 1, $expected); + } else { + $phpcsFile->fixer->addContent($nullable, $expected); + } + } + } } diff --git a/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc b/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc index 57487440..2ab6872a 100644 --- a/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc +++ b/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc @@ -19,4 +19,4 @@ function f(): ? bool {} function g() :bool{} function h(): - ?bool {}; + ?bool {} diff --git a/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc.fixed b/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc.fixed index 9d36f809..faa797ce 100644 --- a/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc.fixed +++ b/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc.fixed @@ -15,4 +15,4 @@ function d() : ?int{} function e() :bool {} function f() :? bool {} function g() :bool{} -function h() :? bool {}; +function h() :? bool {} From 730ba8bda23f4369dd2913c47942d6c779e7b575 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 8 Aug 2017 13:23:08 +0200 Subject: [PATCH 125/225] Fixed .gitattributes - added missing 'export-ignore' - per @weierophinney --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 2ff2155b..b8424729 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,4 @@ -.coveralls.yml +.coveralls.yml export-ignore .gitattributes export-ignore .gitignore export-ignore .travis.yml export-ignore From ffac5b61117ced736788942c01d0ef43b1f5616a Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 8 Aug 2017 13:23:51 +0200 Subject: [PATCH 126/225] Defined allowed simple type hints in sniff instead of using one from common --- src/ZendCodingStandard/CodingStandard.php | 12 ----------- .../Commenting/FunctionCommentSniff.php | 21 ++++++++++++++++++- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/ZendCodingStandard/CodingStandard.php b/src/ZendCodingStandard/CodingStandard.php index d58f26bd..ba4dc447 100644 --- a/src/ZendCodingStandard/CodingStandard.php +++ b/src/ZendCodingStandard/CodingStandard.php @@ -12,18 +12,6 @@ class CodingStandard { - public static $allowedTypes = [ - 'array', - 'bool', - 'float', - 'int', - 'mixed', - 'object', - 'string', - 'resource', - 'callable', - ]; - /** * Returns a valid variable type for param/var tag. * diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 82ff4d49..80da1aff 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -38,6 +38,25 @@ class FunctionCommentSniff extends PEARFunctionCommentSniff */ private $hasInheritDoc = []; + /** + * Allowed simple type hints for method params. + * + * @var array + */ + private $simpleTypeHints = [ + 'array', + 'bool', + 'float', + 'int', + 'object', + 'string', + 'resource', + 'callable', + 'parent', + 'self', + 'iterable', + ]; + /** * @inheritDoc */ @@ -610,7 +629,7 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) $suggestedTypeHint = 'callable'; } elseif (strpos($suggestedName, 'callback') !== false) { $suggestedTypeHint = 'callable'; - } elseif (! in_array($typeName, CodingStandard::$allowedTypes)) { + } elseif (! in_array($typeName, $this->simpleTypeHints, true)) { $suggestedTypeHint = $suggestedName; } elseif ($this->phpVersion >= 70000) { if ($typeName === 'string') { From bfde1ad29c7c1466f1d6dbffc558dd21c4a6eed0 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 8 Aug 2017 13:24:11 +0200 Subject: [PATCH 127/225] Added comments in not implemented empty methods - per @weierophinney --- .../Sniffs/Commenting/VariableCommentSniff.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php index 55565427..923a23d7 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php @@ -115,6 +115,7 @@ public function processMemberVar(File $phpcsFile, $stackPtr) */ protected function processVariable(File $phpcsFile, $stackPtr) { + // Sniff process only class member vars. } /** @@ -122,5 +123,6 @@ protected function processVariable(File $phpcsFile, $stackPtr) */ protected function processVariableInString(File $phpcsFile, $stackPtr) { + // Sniff process only class member vars. } } From c7cd4ac62e8d44e0c6a573a9220dba5b203d4359 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 8 Aug 2017 13:29:26 +0200 Subject: [PATCH 128/225] Bumped PHPUnit to the latest version (^6.3) --- composer.json | 2 +- composer.lock | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/composer.json b/composer.json index 258b035e..47502b38 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "squizlabs/php_codesniffer": "3.0.2" }, "require-dev": { - "phpunit/phpunit": "^5.7.21 || ^6.2.3" + "phpunit/phpunit": "^5.7.21 || ^6.3" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index b061ffb8..31967b48 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "33702ceeea4be9b4e4871c51859ce754", + "content-hash": "3454fdc26d9443a15d82663c4b87ba66", "packages": [ { "name": "squizlabs/php_codesniffer", @@ -211,22 +211,22 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "3.2.0", + "version": "3.2.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "46f7e8bb075036c92695b15a1ddb6971c751e585" + "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/46f7e8bb075036c92695b15a1ddb6971c751e585", - "reference": "46f7e8bb075036c92695b15a1ddb6971c751e585", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/4aada1f93c72c35e22fb1383b47fee43b8f1d157", + "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157", "shasum": "" }, "require": { "php": ">=5.5", "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.4.0", + "phpdocumentor/type-resolver": "^0.3.0", "webmozart/assert": "^1.0" }, "require-dev": { @@ -252,20 +252,20 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-07-15T11:38:20+00:00" + "time": "2017-08-08T06:39:58+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.4.0", + "version": "0.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fb3933512008d8162b3cdf9e18dba9309b7c3773", + "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773", "shasum": "" }, "require": { @@ -299,7 +299,7 @@ "email": "me@mikevanriel.com" } ], - "time": "2017-07-14T14:27:02+00:00" + "time": "2017-06-03T08:32:36+00:00" }, { "name": "phpspec/prophecy", @@ -1269,16 +1269,16 @@ }, { "name": "symfony/yaml", - "version": "v3.3.5", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "1f93a8d19b8241617f5074a123e282575b821df8" + "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/1f93a8d19b8241617f5074a123e282575b821df8", - "reference": "1f93a8d19b8241617f5074a123e282575b821df8", + "url": "https://api.github.com/repos/symfony/yaml/zipball/ddc23324e6cfe066f3dd34a37ff494fa80b617ed", + "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed", "shasum": "" }, "require": { @@ -1320,7 +1320,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-06-15T12:58:50+00:00" + "time": "2017-07-23T12:43:26+00:00" }, { "name": "webmozart/assert", From 84254fb59588b04f0835751ffe237e179afce233 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 23 Aug 2017 11:46:57 +0200 Subject: [PATCH 129/225] Added non-fixable cases for ReturnType sniff --- test/Sniffs/Formatting/ReturnTypeUnitTest.inc | 12 ++++++++++++ test/Sniffs/Formatting/ReturnTypeUnitTest.inc.fixed | 12 ++++++++++++ test/Sniffs/Formatting/ReturnTypeUnitTest.php | 4 ++++ 3 files changed, 28 insertions(+) diff --git a/test/Sniffs/Formatting/ReturnTypeUnitTest.inc b/test/Sniffs/Formatting/ReturnTypeUnitTest.inc index 14cf1974..30653c61 100644 --- a/test/Sniffs/Formatting/ReturnTypeUnitTest.inc +++ b/test/Sniffs/Formatting/ReturnTypeUnitTest.inc @@ -83,3 +83,15 @@ interface MyInterface public function y($a, $b, $c) : \My\TestClass; public function z():? \ReturnType \MyType; } + +class NonFixable +{ + public function a() // comment + : int {} + + public function b() /* comment */ : int {} + + public function c(): // comment + int {} + public function d(): /* comment */ int {} +} diff --git a/test/Sniffs/Formatting/ReturnTypeUnitTest.inc.fixed b/test/Sniffs/Formatting/ReturnTypeUnitTest.inc.fixed index 9e07af3f..4728e5ed 100644 --- a/test/Sniffs/Formatting/ReturnTypeUnitTest.inc.fixed +++ b/test/Sniffs/Formatting/ReturnTypeUnitTest.inc.fixed @@ -81,3 +81,15 @@ interface MyInterface public function y($a, $b, $c): \My\TestClass; public function z(): ?\ReturnType\MyType; } + +class NonFixable +{ + public function a() // comment + : int {} + + public function b() /* comment */ : int {} + + public function c(): // comment + int {} + public function d(): /* comment */ int {} +} diff --git a/test/Sniffs/Formatting/ReturnTypeUnitTest.php b/test/Sniffs/Formatting/ReturnTypeUnitTest.php index 1b9cdb71..7256d6e9 100644 --- a/test/Sniffs/Formatting/ReturnTypeUnitTest.php +++ b/test/Sniffs/Formatting/ReturnTypeUnitTest.php @@ -53,6 +53,10 @@ public function getErrorList($testFile = '') 81 => 1, 83 => 1, 84 => 3, + 89 => 1, + 92 => 1, + 94 => 1, + 96 => 1, ]; } From a7eddd7c802da07750dc0fd2178660f68fb8007f Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 6 Sep 2017 09:00:01 +0100 Subject: [PATCH 130/225] PHP\TypeCasting sniff improvements - changed error codes for each specific error - updated error messages - mapping (real) and (double) casts to (float) as they are the same --- .../Sniffs/PHP/TypeCastingSniff.php | 43 ++++++++----------- test/Sniffs/PHP/TypeCastingUnitTest.inc.fixed | 12 +++--- test/Sniffs/PHP/TypeCastingUnitTest.php | 4 ++ 3 files changed, 27 insertions(+), 32 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php index 99d2d644..5b91e19c 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -1,32 +1,29 @@ '(bool)', + '(integer)' => '(int)', + '(real)' => '(float)', + '(double)' => '(float)', + ]; + /** * @inheritDoc */ public function register() { - return array_merge(Tokens::$castTokens, [T_BOOLEAN_NOT]); + return Tokens::$castTokens + + [T_BOOLEAN_NOT => T_BOOLEAN_NOT]; } /** @@ -36,14 +33,13 @@ public function process(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); - // Process !! casts if ($tokens[$stackPtr]['code'] === T_BOOLEAN_NOT) { $nextToken = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); - if ($tokens[$nextToken]['code'] !== T_BOOLEAN_NOT) { + if (! $nextToken || $tokens[$nextToken]['code'] !== T_BOOLEAN_NOT) { return; } - $error = 'Usage of !! cast is not allowed. Please use (bool) to cast.'; - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed'); + $error = 'Double negation casting is not allowed. Please use (bool) instead.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'DoubleNot'); if ($fix) { $phpcsFile->fixer->beginChangeset(); @@ -60,21 +56,16 @@ public function process(File $phpcsFile, $stackPtr) return; } - // Only allow short forms if both short and long forms are possible - $matching = [ - '(boolean)' => '(bool)', - '(integer)' => '(int)', - ]; $content = $tokens[$stackPtr]['content']; - $key = preg_replace('/\s/', '', strtolower($content)); - if (isset($matching[$key]) || $content !== $key) { - $error = 'Please use %s instead of %s.'; - $expected = isset($matching[$key]) ? $matching[$key] : $key; + $expected = preg_replace('/\s/', '', strtolower($content)); + if ($content !== $expected || isset($this->castMap[$expected])) { + $error = 'Invalid casting used. Expected %s, found %s'; + $expected = isset($this->castMap[$expected]) ? $this->castMap[$expected] : $expected; $data = [ $expected, $content, ]; - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed', $data); + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Invalid', $data); if ($fix) { $phpcsFile->fixer->replaceToken($stackPtr, $expected); diff --git a/test/Sniffs/PHP/TypeCastingUnitTest.inc.fixed b/test/Sniffs/PHP/TypeCastingUnitTest.inc.fixed index 14a8caa3..c3ad35a2 100644 --- a/test/Sniffs/PHP/TypeCastingUnitTest.inc.fixed +++ b/test/Sniffs/PHP/TypeCastingUnitTest.inc.fixed @@ -11,9 +11,9 @@ (int)$var; (bool)$var; (string)$var; -(double)$var; (float)$var; -(real)$var; +(float)$var; +(float)$var; (unset)$var; (bool) $var; @@ -23,9 +23,9 @@ (int) $var; (bool) $var; (string) $var; -(double) $var; +(float) $var; (float) $var; -(real) $var; +(float) $var; (unset) $var; (bool) $var; @@ -43,7 +43,7 @@ (int) $var; (bool) $var; (string) $var; -(double) $var; +(float) $var; (float) $var; -(real) $var; +(float) $var; (UNSET) $var; diff --git a/test/Sniffs/PHP/TypeCastingUnitTest.php b/test/Sniffs/PHP/TypeCastingUnitTest.php index a7e22957..40b67698 100644 --- a/test/Sniffs/PHP/TypeCastingUnitTest.php +++ b/test/Sniffs/PHP/TypeCastingUnitTest.php @@ -12,9 +12,13 @@ public function getErrorList($testFile = '') 5 => 1, 7 => 1, 8 => 1, + 14 => 1, + 16 => 1, 17 => 1, 19 => 1, 20 => 1, + 26 => 1, + 28 => 1, 29 => 1, 31 => 1, 32 => 1, From 0743bcabecaa2860ece6a0f9c403fcabba628e62 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 6 Sep 2017 11:40:46 +0100 Subject: [PATCH 131/225] Added sniff to import internal PHP constants - disabled by default --- ruleset.xml | 3 + .../PHP/ImportInternalConstantSniff.php | 277 ++++++++++++++++++ .../PHP/ImportInternalConstantUnitTest.1.inc | 19 ++ ...ImportInternalConstantUnitTest.1.inc.fixed | 24 ++ .../PHP/ImportInternalConstantUnitTest.2.inc | 6 + ...ImportInternalConstantUnitTest.2.inc.fixed | 9 + .../PHP/ImportInternalConstantUnitTest.inc | 24 ++ .../ImportInternalConstantUnitTest.inc.fixed | 31 ++ .../PHP/ImportInternalConstantUnitTest.php | 39 +++ 9 files changed, 432 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php create mode 100644 test/Sniffs/PHP/ImportInternalConstantUnitTest.1.inc create mode 100644 test/Sniffs/PHP/ImportInternalConstantUnitTest.1.inc.fixed create mode 100644 test/Sniffs/PHP/ImportInternalConstantUnitTest.2.inc create mode 100644 test/Sniffs/PHP/ImportInternalConstantUnitTest.2.inc.fixed create mode 100644 test/Sniffs/PHP/ImportInternalConstantUnitTest.inc create mode 100644 test/Sniffs/PHP/ImportInternalConstantUnitTest.inc.fixed create mode 100644 test/Sniffs/PHP/ImportInternalConstantUnitTest.php diff --git a/ruleset.xml b/ruleset.xml index cc78c114..b66b5d03 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -3,6 +3,9 @@ + + + diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php new file mode 100644 index 00000000..aec17db2 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php @@ -0,0 +1,277 @@ + Hash map of all php built in constant names. + */ + private $builtInConstants; + + /** + * @var File Currently processed file. + */ + private $currentFile; + + /** + * @var string Currently processed namespace. + */ + private $currentNamespace; + + /** + * @var array Array of imported constant in current namespace. + */ + private $importedConstants; + + /** + * @var null|int Last use statement position. + */ + private $lastUse; + + public function __construct() + { + $allConstants = get_defined_constants(true); + + $arr = []; + array_walk_recursive($allConstants, function ($v, $k) use (&$arr) { + if (strtolower($k) !== 'user') { + $arr[$k] = $v; + } + }); + + $this->builtInConstants = $arr; + } + + /** + * @inheritDoc + */ + public function register() + { + return [T_STRING]; + } + + /** + * @inheritDoc + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->currentFile !== $phpcsFile) { + $this->currentFile = $phpcsFile; + $this->currentNamespace = null; + } + + $namespace = $this->getNamespace($phpcsFile, $stackPtr); + if ($this->currentNamespace !== $namespace) { + $this->currentNamespace = $namespace; + $this->importedConstants = $this->getImportedConstants($phpcsFile, $stackPtr); + } + + $tokens = $phpcsFile->getTokens(); + + $content = strtoupper($tokens[$stackPtr]['content']); + if ($content !== $tokens[$stackPtr]['content']) { + return; + } + + if (! isset($this->builtInConstants[$content])) { + return; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); + if ($next && $tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + return; + } + + $prev = $phpcsFile->findPrevious( + Tokens::$emptyTokens + [T_BITWISE_AND => T_BITWISE_AND, T_NS_SEPARATOR => T_NS_SEPARATOR], + $stackPtr - 1, + null, + true + ); + if ($tokens[$prev]['code'] === T_FUNCTION + || $tokens[$prev]['code'] === T_NEW + || $tokens[$prev]['code'] === T_STRING + || $tokens[$prev]['code'] === T_DOUBLE_COLON + || $tokens[$prev]['code'] === T_OBJECT_OPERATOR + ) { + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); + if ($tokens[$prev]['code'] === T_NS_SEPARATOR) { + if (isset($this->importedConstants[$content])) { + if (strtoupper($this->importedConstants[$content]['fqn']) === $content) { + $error = 'FQN for PHP internal constant "%s" is not needed here, constant is already imported'; + $data = [ + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'RedundantFQN', $data); + if ($fix) { + $phpcsFile->fixer->replaceToken($prev, ''); + } + } + } else { + $error = 'PHP internal constant "%s" must be imported'; + $data = [ + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ImportFQN', $data); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($prev, ''); + $this->importConstant($phpcsFile, $stackPtr, $content); + $phpcsFile->fixer->endChangeset(); + } + } + } else { + if (! isset($this->importedConstants[$content])) { + $error = 'PHP internal constant "%s" must be imported'; + $data = [ + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Import', $data); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $this->importConstant($phpcsFile, $stackPtr, $content); + $phpcsFile->fixer->endChangeset(); + } + } + } + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @return string + */ + private function getNamespace(File $phpcsFile, $stackPtr) + { + if ($nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr - 1)) { + $nsEnd = $phpcsFile->findNext([T_NS_SEPARATOR, T_STRING, T_WHITESPACE], $nsStart + 1, null, true); + return trim($phpcsFile->getTokensAsString($nsStart + 1, $nsEnd - $nsStart - 1)); + } + + return ''; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @return array + */ + private function getImportedConstants(File $phpcsFile, $stackPtr) + { + $first = 0; + $last = $phpcsFile->numTokens; + + $tokens = $phpcsFile->getTokens(); + + $nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr); + if ($nsStart && isset($tokens[$nsStart]['scope_opener'])) { + $first = $tokens[$nsStart]['scope_opener']; + $last = $tokens[$nsStart]['scope_closer']; + } + + $this->lastUse = null; + $constants = []; + + $use = $first; + while ($use = $phpcsFile->findNext(T_USE, $use + 1, $last)) { + if (CodingStandard::isGlobalUse($phpcsFile, $use)) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $use + 1, null, true); + if ($tokens[$next]['code'] === T_STRING + && strtolower($tokens[$next]['content']) === 'const' + ) { + $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); + $end = $phpcsFile->findPrevious( + T_STRING, + $phpcsFile->findNext([T_AS, T_SEMICOLON], $start + 1) - 1 + ); + $endOfStatement = $phpcsFile->findEndOfStatement($next); + $name = $phpcsFile->findPrevious(T_STRING, $endOfStatement - 1); + $fullName = $phpcsFile->getTokensAsString($start, $end - $start + 1); + + $constants[strtoupper($tokens[$name]['content'])] = [ + 'name' => $tokens[$name]['content'], + 'fqn' => ltrim($fullName, '\\'), + ]; + + $this->lastUse = $use; + } + } + + if (! $this->lastUse) { + $this->lastUse = $use; + } + } + + return $constants; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @param string $constantName + */ + private function importConstant(File $phpcsFile, $stackPtr, $constantName) + { + if ($this->lastUse) { + $ptr = $phpcsFile->findEndOfStatement($this->lastUse); + } else { + $nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr); + if ($nsStart) { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$nsStart]['scope_opener'])) { + $ptr = $tokens[$nsStart]['scope_opener']; + } else { + $ptr = $phpcsFile->findEndOfStatement($nsStart); + $phpcsFile->fixer->addNewline($ptr); + } + } else { + $ptr = $phpcsFile->findPrevious(T_OPEN_TAG, $stackPtr - 1); + } + } + + $phpcsFile->fixer->addNewline($ptr); + $phpcsFile->fixer->addContent($ptr, sprintf('use const %s;', $constantName)); + if (! $this->lastUse && (! $nsStart || isset($tokens[$nsStart]['scope_opener']))) { + $phpcsFile->fixer->addNewline($ptr); + } + + $this->importedConstants[$constantName] = [ + 'name' => $constantName, + 'fqn' => $constantName, + ]; + } +} diff --git a/test/Sniffs/PHP/ImportInternalConstantUnitTest.1.inc b/test/Sniffs/PHP/ImportInternalConstantUnitTest.1.inc new file mode 100644 index 00000000..7e0522f9 --- /dev/null +++ b/test/Sniffs/PHP/ImportInternalConstantUnitTest.1.inc @@ -0,0 +1,19 @@ +E_ERROR; +$z = $obj::ATOM; + +function SEEK_CUR() { +} + +SEEK_CUR(); + +$b = &T_WHITESPACE; + +define('MY_CONST', 'value'); +$myConst = MY_CONST; + +$c = \T_VAR; diff --git a/test/Sniffs/PHP/ImportInternalConstantUnitTest.inc.fixed b/test/Sniffs/PHP/ImportInternalConstantUnitTest.inc.fixed new file mode 100644 index 00000000..0f0b713d --- /dev/null +++ b/test/Sniffs/PHP/ImportInternalConstantUnitTest.inc.fixed @@ -0,0 +1,31 @@ +E_ERROR; +$z = $obj::ATOM; + +function SEEK_CUR() { +} + +SEEK_CUR(); + +$b = &T_WHITESPACE; + +define('MY_CONST', 'value'); +$myConst = MY_CONST; + +$c = T_VAR; diff --git a/test/Sniffs/PHP/ImportInternalConstantUnitTest.php b/test/Sniffs/PHP/ImportInternalConstantUnitTest.php new file mode 100644 index 00000000..cda3406c --- /dev/null +++ b/test/Sniffs/PHP/ImportInternalConstantUnitTest.php @@ -0,0 +1,39 @@ + 1, + 5 => 1, + 11 => 1, + 12 => 1, + 18 => 1, + ]; + case 'ImportInternalConstantUnitTest.2.inc': + return [ + 5 => 1, + 6 => 1, + ]; + } + + return [ + 3 => 1, + 5 => 1, + 6 => 2, + 19 => 1, + 24 => 1, + ]; + } + + public function getWarningList($testFile = '') + { + return []; + } +} From ade1c6a81edbae8a0f1e21809fa669d5b0c4fc3a Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 6 Sep 2017 11:45:13 +0100 Subject: [PATCH 132/225] Import PHP internal constants --- src/ZendCodingStandard/CodingStandard.php | 5 +++ .../Sniffs/Arrays/FormatSniff.php | 6 +++ .../Sniffs/Arrays/TrailingArrayCommaSniff.php | 12 +++++ .../AlphabeticallySortedTraitsSniff.php | 9 ++++ .../Sniffs/Classes/NoNullValuesSniff.php | 4 ++ .../Sniffs/Classes/TraitUsageSniff.php | 10 +++++ .../Sniffs/Commenting/DocCommentSniff.php | 12 +++++ .../Commenting/FunctionCommentSniff.php | 14 ++++++ .../Commenting/VariableCommentSniff.php | 10 +++++ .../Sniffs/Formatting/DoubleColonSniff.php | 3 ++ .../Sniffs/Formatting/NewKeywordSniff.php | 3 ++ .../Formatting/NoSpaceAfterSplatSniff.php | 3 ++ .../Sniffs/Formatting/ReferenceSniff.php | 6 +++ .../Sniffs/Formatting/ReturnTypeSniff.php | 10 +++++ .../UnnecessaryParenthesesSniff.php | 41 +++++++++++++++++ .../Sniffs/Methods/LineAfterSniff.php | 9 ++++ .../AlphabeticallySortedUsesSniff.php | 6 +++ .../ConstAndFunctionKeywordsSniff.php | 3 ++ .../Namespaces/UnusedUseStatementSniff.php | 12 +++++ .../UseDoesNotStartWithBackslashSniff.php | 5 +++ .../ValidVariableNameSniff.php | 3 ++ .../Sniffs/Operators/BooleanOperatorSniff.php | 2 + .../Sniffs/Operators/TernaryOperatorSniff.php | 4 ++ .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 25 +++++++++++ .../PHP/ImportInternalFunctionSniff.php | 15 +++++++ .../PHP/InstantiatingParenthesisSniff.php | 9 ++++ .../Sniffs/PHP/LowerCaseKeywordSniff.php | 5 +++ .../Sniffs/PHP/RedundantSemicolonSniff.php | 5 +++ .../Sniffs/PHP/TypeCastingSniff.php | 4 ++ .../Strings/NoConcatenationAtTheEndSniff.php | 3 ++ .../Sniffs/WhiteSpace/BlankLineSniff.php | 4 ++ .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 6 +++ .../WhiteSpace/NoBlankLineAtStartSniff.php | 7 +++ .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 45 +++++++++++++++++++ test/Sniffs/TestCase.php | 3 ++ 35 files changed, 323 insertions(+) diff --git a/src/ZendCodingStandard/CodingStandard.php b/src/ZendCodingStandard/CodingStandard.php index ba4dc447..1835c637 100644 --- a/src/ZendCodingStandard/CodingStandard.php +++ b/src/ZendCodingStandard/CodingStandard.php @@ -10,6 +10,11 @@ use function strpos; use function strtolower; +use const T_ANON_CLASS; +use const T_CLASS; +use const T_OPEN_PARENTHESIS; +use const T_TRAIT; + class CodingStandard { /** diff --git a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index 318a3684..93151d9b 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -8,6 +8,12 @@ use function strlen; use function strpos; +use const T_CLOSE_SHORT_ARRAY; +use const T_COMMENT; +use const T_DOUBLE_ARROW; +use const T_OPEN_SHORT_ARRAY; +use const T_WHITESPACE; + class FormatSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php index a187be9d..7ded102c 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php @@ -9,6 +9,18 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; +use const T_COMMA; +use const T_COMMENT; +use const T_DOC_COMMENT; +use const T_DOC_COMMENT_CLOSE_TAG; +use const T_DOC_COMMENT_OPEN_TAG; +use const T_DOC_COMMENT_STAR; +use const T_DOC_COMMENT_STRING; +use const T_DOC_COMMENT_TAG; +use const T_DOC_COMMENT_WHITESPACE; +use const T_OPEN_SHORT_ARRAY; +use const T_WHITESPACE; + class TrailingArrayCommaSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php index 7fb39747..ca63f1fe 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php @@ -14,6 +14,15 @@ use function trim; use function uasort; +use const T_ANON_CLASS; +use const T_CLASS; +use const T_CLOSE_CURLY_BRACKET; +use const T_COMMA; +use const T_OPEN_CURLY_BRACKET; +use const T_SEMICOLON; +use const T_TRAIT; +use const T_USE; + class AlphabeticallySortedTraitsSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php b/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php index 422d789a..224bb605 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php @@ -7,6 +7,10 @@ use function in_array; +use const T_EQUAL; +use const T_NULL; +use const T_WHITESPACE; + class NoNullValuesSniff extends AbstractVariableSniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php index 88ac2c7f..519e46df 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php @@ -12,6 +12,16 @@ use function strcasecmp; use function usort; +use const T_ANON_CLASS; +use const T_CLASS; +use const T_CLOSE_CURLY_BRACKET; +use const T_COMMA; +use const T_OPEN_CURLY_BRACKET; +use const T_SEMICOLON; +use const T_TRAIT; +use const T_USE; +use const T_WHITESPACE; + class TraitUsageSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index bbb70344..23eb089f 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -11,6 +11,18 @@ use function strpos; use function trim; +use const T_DOC_COMMENT_CLOSE_TAG; +use const T_DOC_COMMENT_OPEN_TAG; +use const T_DOC_COMMENT_STAR; +use const T_DOC_COMMENT_STRING; +use const T_DOC_COMMENT_TAG; +use const T_DOC_COMMENT_WHITESPACE; +use const T_NAMESPACE; +use const T_OPEN_CURLY_BRACKET; +use const T_OPEN_TAG; +use const T_USE; +use const T_WHITESPACE; + class DocCommentSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 80da1aff..043f6700 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -22,6 +22,20 @@ use function substr; use function trim; +use const PHP_VERSION_ID; +use const T_CLOSURE; +use const T_DOC_COMMENT_CLOSE_TAG; +use const T_DOC_COMMENT_OPEN_TAG; +use const T_DOC_COMMENT_STAR; +use const T_DOC_COMMENT_STRING; +use const T_DOC_COMMENT_WHITESPACE; +use const T_FUNCTION; +use const T_RETURN; +use const T_SEMICOLON; +use const T_STRING; +use const T_WHITESPACE; +use const T_YIELD; + class FunctionCommentSniff extends PEARFunctionCommentSniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php index 923a23d7..c0d86481 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php @@ -12,6 +12,16 @@ use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; use ZendCodingStandard\CodingStandard; +use const T_COMMENT; +use const T_DOC_COMMENT_CLOSE_TAG; +use const T_DOC_COMMENT_STRING; +use const T_PRIVATE; +use const T_PROTECTED; +use const T_PUBLIC; +use const T_STATIC; +use const T_VAR; +use const T_WHITESPACE; + class VariableCommentSniff extends AbstractVariableSniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php index 37d69bb2..0effecc2 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php @@ -4,6 +4,9 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; +use const T_DOUBLE_COLON; +use const T_WHITESPACE; + class DoubleColonSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php index 543cd789..12cc3223 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php @@ -4,6 +4,9 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; +use const T_NEW; +use const T_WHITESPACE; + class NewKeywordSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php index d67e8fe7..ce6b274c 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php @@ -4,6 +4,9 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; +use const T_ELLIPSIS; +use const T_WHITESPACE; + class NoSpaceAfterSplatSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php index 77b6cb94..35df9429 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php @@ -7,6 +7,12 @@ use function in_array; +use const T_BITWISE_AND; +use const T_COMMA; +use const T_OPEN_PARENTHESIS; +use const T_OPEN_SHORT_ARRAY; +use const T_WHITESPACE; + class ReferenceSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php index ca40d195..33ae9995 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php @@ -10,6 +10,16 @@ use function strtolower; use function trim; +use const T_CLOSE_PARENTHESIS; +use const T_COLON; +use const T_NS_SEPARATOR; +use const T_NULLABLE; +use const T_OPEN_CURLY_BRACKET; +use const T_RETURN_TYPE; +use const T_SEMICOLON; +use const T_STRING; +use const T_WHITESPACE; + class ReturnTypeSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php index 4ba9841c..b1dc9e41 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -7,6 +7,47 @@ use function in_array; +use const T_ANON_CLASS; +use const T_BITWISE_AND; +use const T_BITWISE_OR; +use const T_BITWISE_XOR; +use const T_BOOLEAN_NOT; +use const T_CLONE; +use const T_CLOSE_CURLY_BRACKET; +use const T_CLOSE_PARENTHESIS; +use const T_CLOSE_SHORT_ARRAY; +use const T_CLOSE_SQUARE_BRACKET; +use const T_CLOSE_TAG; +use const T_COALESCE; +use const T_COLON; +use const T_COMMA; +use const T_DOUBLE_ARROW; +use const T_ECHO; +use const T_EMPTY; +use const T_EVAL; +use const T_EXIT; +use const T_INCLUDE; +use const T_INCLUDE_ONCE; +use const T_INLINE_ELSE; +use const T_INLINE_THEN; +use const T_INSTANCEOF; +use const T_ISSET; +use const T_LIST; +use const T_OBJECT_OPERATOR; +use const T_OPEN_PARENTHESIS; +use const T_OPEN_TAG; +use const T_REQUIRE; +use const T_REQUIRE_ONCE; +use const T_RETURN; +use const T_SELF; +use const T_SEMICOLON; +use const T_STATIC; +use const T_STRING; +use const T_STRING_CONCAT; +use const T_UNSET; +use const T_USE; +use const T_VARIABLE; + class UnnecessaryParenthesesSniff implements Sniff { private $parenthesesAllowedTokens = [ diff --git a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php index c44fadb1..916d681e 100644 --- a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php +++ b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php @@ -6,6 +6,15 @@ use function max; +use const T_ANON_CLASS; +use const T_CLASS; +use const T_CLOSE_CURLY_BRACKET; +use const T_FUNCTION; +use const T_INTERFACE; +use const T_SEMICOLON; +use const T_TRAIT; +use const T_WHITESPACE; + class LineAfterSniff extends AbstractScopeSniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php index dc50041e..9f58f46d 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -15,6 +15,12 @@ use function trim; use function uasort; +use const T_NAMESPACE; +use const T_NS_SEPARATOR; +use const T_SEMICOLON; +use const T_STRING; +use const T_USE; + class AlphabeticallySortedUsesSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php index 5b291ab7..ec7ec8d0 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php @@ -8,6 +8,9 @@ use function strtolower; +use const T_USE; +use const T_WHITESPACE; + class ConstAndFunctionKeywordsSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index 2ba90989..145f300e 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -27,6 +27,18 @@ use function strtolower; use function trim; +use const T_AS; +use const T_DOC_COMMENT_STRING; +use const T_DOC_COMMENT_TAG; +use const T_NAMESPACE; +use const T_NS_SEPARATOR; +use const T_OBJECT_OPERATOR; +use const T_RETURN_TYPE; +use const T_SEMICOLON; +use const T_STRING; +use const T_USE; +use const T_WHITESPACE; + class UnusedUseStatementSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php index f8ca75d9..e1473861 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php @@ -8,6 +8,11 @@ use function strtolower; +use const T_NS_SEPARATOR; +use const T_STRING; +use const T_USE; +use const T_WHITESPACE; + class UseDoesNotStartWithBackslashSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php index cb4927e4..20430b72 100644 --- a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php +++ b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -14,6 +14,9 @@ use function in_array; use function ltrim; +use const T_DOUBLE_COLON; +use const T_WHITESPACE; + class ValidVariableNameSniff extends AbstractVariableSniff { const CODE_CAMEL_CAPS = 'NotCamelCaps'; diff --git a/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php b/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php index c5cca5b6..c6151da7 100644 --- a/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php +++ b/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php @@ -5,6 +5,8 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use const T_WHITESPACE; + class BooleanOperatorSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php b/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php index 773e53e8..a8efec50 100644 --- a/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php +++ b/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php @@ -5,6 +5,10 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use const T_INLINE_ELSE; +use const T_INLINE_THEN; +use const T_WHITESPACE; + class TernaryOperatorSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index 30def5c2..a2801975 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -23,6 +23,31 @@ use function substr; use function trim; +use const T_AS; +use const T_CLOSURE; +use const T_COLON; +use const T_COMMA; +use const T_DOC_COMMENT_STRING; +use const T_DOC_COMMENT_TAG; +use const T_DOC_COMMENT_WHITESPACE; +use const T_DOUBLE_COLON; +use const T_EXTENDS; +use const T_FUNCTION; +use const T_IMPLEMENTS; +use const T_NAMESPACE; +use const T_NEW; +use const T_NS_SEPARATOR; +use const T_NULLABLE; +use const T_OPEN_PARENTHESIS; +use const T_PARENT; +use const T_RETURN_TYPE; +use const T_SELF; +use const T_STATIC; +use const T_STRING; +use const T_USE; +use const T_VARIABLE; +use const T_WHITESPACE; + /** * TODO: Better results for this sniff we will have if the parsed class is imported. * We can "include" the file on process, but probably it is not the best solution. diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php index f1e65c4f..f6c5e1c3 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php @@ -13,6 +13,21 @@ use function strtolower; use function trim; +use const T_AS; +use const T_BITWISE_AND; +use const T_DOUBLE_COLON; +use const T_FUNCTION; +use const T_NAMESPACE; +use const T_NEW; +use const T_NS_SEPARATOR; +use const T_OBJECT_OPERATOR; +use const T_OPEN_PARENTHESIS; +use const T_OPEN_TAG; +use const T_SEMICOLON; +use const T_STRING; +use const T_USE; +use const T_WHITESPACE; + class ImportInternalFunctionSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php index fdaf34d9..54fbb94f 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php @@ -7,6 +7,15 @@ use function array_merge; +use const T_ANON_CLASS; +use const T_NEW; +use const T_NS_SEPARATOR; +use const T_OPEN_PARENTHESIS; +use const T_SELF; +use const T_STATIC; +use const T_STRING; +use const T_VARIABLE; + class InstantiatingParenthesisSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php b/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php index 4b67e35f..b7dbbd6d 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php @@ -5,6 +5,11 @@ use function array_merge; +use const T_CLOSURE; +use const T_PARENT; +use const T_SELF; +use const T_YIELD; + class LowerCaseKeywordSniff extends GenericLowerCaseKeywordSniff { /** diff --git a/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php b/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php index 16a4d78c..3e6708ee 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php @@ -8,6 +8,11 @@ use function in_array; use function strtolower; +use const T_ANON_CLASS; +use const T_CLOSE_CURLY_BRACKET; +use const T_CLOSURE; +use const T_SEMICOLON; + class RedundantSemicolonSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php index 5b91e19c..6f37d402 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -8,6 +8,10 @@ use function preg_replace; use function strtolower; +use const T_BOOLEAN_NOT; +use const T_UNSET_CAST; +use const T_WHITESPACE; + class TypeCastingSniff implements Sniff { private $castMap = [ diff --git a/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php b/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php index ba3ee71c..2cf7a3c9 100644 --- a/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php +++ b/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php @@ -4,6 +4,9 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; +use const T_STRING_CONCAT; +use const T_WHITESPACE; + class NoConcatenationAtTheEndSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php index 317f2bc5..d4da4346 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php @@ -4,6 +4,10 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; +use const T_COMMENT; +use const T_OPEN_TAG; +use const T_WHITESPACE; + class BlankLineSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index f302c626..f07aa3e8 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -22,6 +22,12 @@ use function array_merge; use function strlen; +use const T_CLOSE_SHORT_ARRAY; +use const T_COMMA; +use const T_DOUBLE_ARROW; +use const T_OPEN_SHORT_ARRAY; +use const T_WHITESPACE; + class CommaSpacingSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php index 2051e8a2..be1ea88c 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php @@ -4,6 +4,13 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; +use const T_CLASS; +use const T_CLOSURE; +use const T_FUNCTION; +use const T_INTERFACE; +use const T_TRAIT; +use const T_WHITESPACE; + class NoBlankLineAtStartSniff implements Sniff { /** diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index 239ea7d2..2391f0da 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -15,6 +15,51 @@ use function strpos; use function substr; +use const T_ARRAY; +use const T_BREAK; +use const T_CATCH; +use const T_CLASS; +use const T_CLOSE_CURLY_BRACKET; +use const T_CLOSE_PARENTHESIS; +use const T_CLOSE_SHORT_ARRAY; +use const T_CLOSURE; +use const T_COLON; +use const T_COMMA; +use const T_COMMENT; +use const T_CONSTANT_ENCAPSED_STRING; +use const T_CONTINUE; +use const T_DOC_COMMENT_OPEN_TAG; +use const T_DOUBLE_QUOTED_STRING; +use const T_ELSEIF; +use const T_EXIT; +use const T_FOR; +use const T_FOREACH; +use const T_FUNCTION; +use const T_GOTO_LABEL; +use const T_IF; +use const T_INLINE_ELSE; +use const T_INLINE_HTML; +use const T_INLINE_THEN; +use const T_OBJECT_OPERATOR; +use const T_OPEN_CURLY_BRACKET; +use const T_OPEN_PARENTHESIS; +use const T_OPEN_SHORT_ARRAY; +use const T_OPEN_TAG; +use const T_RETURN; +use const T_SELF; +use const T_SEMICOLON; +use const T_START_HEREDOC; +use const T_START_NOWDOC; +use const T_STATIC; +use const T_STRING; +use const T_STRING_CONCAT; +use const T_SWITCH; +use const T_THROW; +use const T_USE; +use const T_VARIABLE; +use const T_WHILE; +use const T_WHITESPACE; + class ScopeIndentSniff implements Sniff { public $indent = 4; diff --git a/test/Sniffs/TestCase.php b/test/Sniffs/TestCase.php index 8d479759..f6996bbe 100644 --- a/test/Sniffs/TestCase.php +++ b/test/Sniffs/TestCase.php @@ -26,6 +26,9 @@ use function substr; use function trim; +use const DIRECTORY_SEPARATOR; +use const PHP_EOL; + abstract class TestCase extends \PHPUnit\Framework\TestCase { /** From 828ee22e5a78320eda4c0515b35b9203321aeeb9 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 6 Sep 2017 11:45:57 +0100 Subject: [PATCH 133/225] Renamed property --- .../Sniffs/PHP/ImportInternalFunctionSniff.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php index f6c5e1c3..5ae8f546 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php @@ -48,7 +48,7 @@ class ImportInternalFunctionSniff implements Sniff /** * @var array Array of imported function in current namespace. */ - private $importedFunction; + private $importedFunctions; /** * @var null|int Last use statement position. @@ -82,7 +82,7 @@ public function process(File $phpcsFile, $stackPtr) $namespace = $this->getNamespace($phpcsFile, $stackPtr); if ($this->currentNamespace !== $namespace) { $this->currentNamespace = $namespace; - $this->importedFunction = $this->getImportedFunctions($phpcsFile, $stackPtr); + $this->importedFunctions = $this->getImportedFunctions($phpcsFile, $stackPtr); } $tokens = $phpcsFile->getTokens(); @@ -115,8 +115,8 @@ public function process(File $phpcsFile, $stackPtr) $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] === T_NS_SEPARATOR) { - if (isset($this->importedFunction[$content])) { - if (strtolower($this->importedFunction[$content]['fqn']) === $content) { + if (isset($this->importedFunctions[$content])) { + if (strtolower($this->importedFunctions[$content]['fqn']) === $content) { $error = 'FQN for PHP internal function "%s" is not needed here, function is already imported'; $data = [ $content, @@ -142,7 +142,7 @@ public function process(File $phpcsFile, $stackPtr) } } } else { - if (! isset($this->importedFunction[$content])) { + if (! isset($this->importedFunctions[$content])) { $error = 'PHP internal function "%s" must be imported'; $data = [ $content, @@ -257,7 +257,7 @@ private function importFunction(File $phpcsFile, $stackPtr, $functionName) $phpcsFile->fixer->addNewline($ptr); } - $this->importedFunction[$functionName] = [ + $this->importedFunctions[$functionName] = [ 'name' => $functionName, 'fqn' => $functionName, ]; From d1584c7b8a672e45695ae534af18bf84b94e53dc Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 6 Sep 2017 11:46:27 +0100 Subject: [PATCH 134/225] Moved condition to check if function is defined to return earlier --- .../Sniffs/PHP/ImportInternalFunctionSniff.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php index 5ae8f546..5f645eec 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php @@ -93,6 +93,11 @@ public function process(File $phpcsFile, $stackPtr) return; } + $content = strtolower($tokens[$stackPtr]['content']); + if (! isset($this->builtInFunctions[$content])) { + return; + } + $prev = $phpcsFile->findPrevious( Tokens::$emptyTokens + [T_BITWISE_AND => T_BITWISE_AND, T_NS_SEPARATOR => T_NS_SEPARATOR], $stackPtr - 1, @@ -108,11 +113,6 @@ public function process(File $phpcsFile, $stackPtr) return; } - $content = strtolower($tokens[$stackPtr]['content']); - if (! isset($this->builtInFunctions[$content])) { - return; - } - $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] === T_NS_SEPARATOR) { if (isset($this->importedFunctions[$content])) { From 7ae16bb25fe2409208436e9b4d509b11ba6600d7 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 6 Sep 2017 11:47:07 +0100 Subject: [PATCH 135/225] Single element array changed to one line --- src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index 2391f0da..d0a89ad5 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -137,9 +137,7 @@ public function __construct() */ public function register() { - return [ - T_OPEN_TAG, - ]; + return [T_OPEN_TAG]; } /** From dd6c45c71a486d724107c92fdb79d95bf461d91c Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 6 Sep 2017 11:50:28 +0100 Subject: [PATCH 136/225] Added bracket to clarify statement --- src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index 23eb089f..e75c21a5 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -372,8 +372,8 @@ private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEn $next = $commentStart; $search = [T_DOC_COMMENT_STAR, T_DOC_COMMENT_CLOSE_TAG]; while ($next = $phpcsFile->findNext($search, $next + 1, $commentEnd + 1)) { - if ($tokens[$next]['code'] === T_DOC_COMMENT_STAR - && $tokens[$next + 1]['code'] !== T_DOC_COMMENT_WHITESPACE + if (($tokens[$next + 1]['code'] !== T_DOC_COMMENT_WHITESPACE + && $tokens[$next]['code'] === T_DOC_COMMENT_STAR) || ($tokens[$next + 1]['code'] === T_DOC_COMMENT_WHITESPACE && strpos($tokens[$next + 1]['content'], $phpcsFile->eolChar) === false) ) { From 89603503dde335b7b469816ea9feaf74010da5a3 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 6 Sep 2017 13:29:32 +0100 Subject: [PATCH 137/225] Spacing in PHPDocs - around tags and types --- .../Sniffs/Commenting/DocCommentSniff.php | 176 +++++++++++++++++- .../Commenting/FunctionCommentSniff.php | 4 +- .../Namespaces/UnusedUseStatementSniff.php | 5 +- .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 10 +- test/Sniffs/Commenting/DocCommentUnitTest.inc | 52 ++++++ .../Commenting/DocCommentUnitTest.inc.fixed | 54 ++++++ test/Sniffs/Commenting/DocCommentUnitTest.php | 16 ++ 7 files changed, 306 insertions(+), 11 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index e75c21a5..5e99e4b3 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -4,11 +4,18 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; +use function array_filter; +use function implode; use function in_array; +use function ltrim; +use function max; use function preg_match; +use function preg_split; +use function round; use function str_repeat; use function strlen; use function strpos; +use function strtolower; use function trim; use const T_DOC_COMMENT_CLOSE_TAG; @@ -25,6 +32,15 @@ class DocCommentSniff implements Sniff { + public $indent = 4; + + private $tagWithType = [ + '@var', + '@param', + '@return', + '@throws', + ]; + /** * @inheritDoc */ @@ -49,6 +65,7 @@ public function process(File $phpcsFile, $stackPtr) $this->checkBeforeOpen($phpcsFile, $commentStart); $this->checkAfterClose($phpcsFile, $commentStart, $commentEnd); $this->checkCommentIndents($phpcsFile, $commentStart, $commentEnd); + $this->checkTagsSpaces($phpcsFile, $commentStart); // Doc block comment in one line. if ($tokens[$commentStart]['line'] == $tokens[$commentEnd]['line']) { @@ -334,6 +351,7 @@ private function checkSpacesInOneLineComment(File $phpcsFile, $commentStart, $co } elseif ($tokens[$commentStart + 1]['code'] !== T_DOC_COMMENT_WHITESPACE) { // This case is currently not supported. // Comment /**@var null $name; */ is not recognized as doc-block comment. + // todo: fix is already marged to PHP_CodeSniffer 3.1.0, need to be changed after release 3.1.0 $error = 'Expected 1 space after opening tag of one line doc block comment.'; $fix = $phpcsFile->addFixableError($error, $commentStart, 'InvalidSpacing'); @@ -358,7 +376,7 @@ private function checkSpacesInOneLineComment(File $phpcsFile, $commentStart, $co * Checks if there is one space after star in multiline doc comment. * More than one space is allowed, unless the line contains tag. * - * TODO: needs to check with doctrine annotations + * @todo: needs to check with doctrine annotations * * @param File $phpcsFile * @param int $commentStart @@ -394,6 +412,64 @@ private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEn if ($fix) { $phpcsFile->fixer->replaceToken($next + 1, ' '); } + } elseif ($tokens[$next + 2]['code'] !== T_DOC_COMMENT_TAG + && $tokens[$next + 2]['code'] !== T_DOC_COMMENT_CLOSE_TAG + ) { + $prev = $phpcsFile->findPrevious( + [ + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STRING, + T_DOC_COMMENT_STAR, + ], + $next - 1, + null, + true + ); + + $trimmed = ltrim($tokens[$next + 1]['content']); + $spaces = strlen($tokens[$next + 1]['content']) - strlen($trimmed); + if ($tokens[$prev]['code'] === T_DOC_COMMENT_TAG + && ($spaces < $this->indent + 1 + || (($spaces - 1) % $this->indent) !== 0 + || ($spaces > $this->indent + 1 + && $tokens[$prev]['line'] === $tokens[$next + 1]['line'] - 1)) + ) { + $prev2 = $phpcsFile->findPrevious( + [ + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STAR, + ], + $next - 1, + $prev, + true + ); + + if ($tokens[$prev2]['line'] === $tokens[$next]['line'] - 1) { + if ($tokens[$prev]['line'] === $tokens[$next + 1]['line'] - 1) { + $expectedSpaces = 1 + $this->indent; + } else { + $expectedSpaces = 1 + max( + round(($spaces - 1) / $this->indent) * $this->indent, + $this->indent + ); + } + $error = 'Invalid indent before description; expected %d spaces, found %d'; + $data = [ + $expectedSpaces, + $spaces, + ]; + $fix = $phpcsFile->addFixableError($error, $next + 1, 'InvalidDescriptionIndent', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($next + 1, str_repeat(' ', $expectedSpaces) . $trimmed); + } + } else { + $error = 'Additional description is not allowed after tag.' + . ' Please move description to the top of the PHPDocs' + . ' or remove empty line above if it is description for the tag.'; + $phpcsFile->addError($error, $next + 1, 'AdditionalDescription'); + } + } } } } @@ -642,4 +718,102 @@ private function checkBlankLineBeforeTags(File $phpcsFile, $commentStart) } } } + + /** + * @param File $phpcsFile + * @param int $commentStart + * @return void + */ + private function checkTagsSpaces(File $phpcsFile, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + // Return when there is no tags in the comment. + if (empty($tokens[$commentStart]['comment_tags'])) { + return; + } + + // Return when comment contains one of the following tags. + $skipIfContains = ['@copyright', '@license']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if (in_array(strtolower($tokens[$tag]['content']), $skipIfContains, true)) { + return; + } + } + + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + // Continue if next token is not a whitespace. + if ($tokens[$tag + 1]['code'] !== T_DOC_COMMENT_WHITESPACE) { + continue; + } + + // Continue if next token contains new line. + if (strpos($tokens[$tag + 1]['content'], $phpcsFile->eolChar) !== false) { + continue; + } + + // Continue if after next token the comment ends. + // It means end of the comment is in the same line as the tag. + if ($tokens[$tag + 2]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + continue; + } + + // Check spaces after type for some tags. + if (in_array(strtolower($tokens[$tag]['content']), $this->tagWithType, true) + && $tokens[$tag + 2]['code'] === T_DOC_COMMENT_STRING + ) { + $this->checkSpacesAfterTag($phpcsFile, $tag); + } + + // Continue if next token is one space. + if ($tokens[$tag + 1]['content'] === ' ') { + continue; + } + + $error = 'There must be exactly one space after PHPDoc tag.'; + $fix = $phpcsFile->addFixableError($error, $tag + 1, 'SpaceAfterTag'); + + if ($fix) { + $phpcsFile->fixer->replaceToken($tag + 1, ' '); + } + } + } + + /** + * @param File $phpcsFile + * @param int $tag + * @return void + */ + private function checkSpacesAfterTag(File $phpcsFile, $tag) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$tag + 2]['content']; + $expected = implode(' ', array_filter(preg_split('/\s+/', $content))); + + if ($tokens[$tag + 3]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + // In case when spacing between type and variable is correct. + // Space before closing comment tag are covered in another case. + if (trim($content) === $expected) { + return; + } + + $expected .= ' '; + } + + if ($content === $expected) { + return; + } + + $error = 'Invalid spacing in comment; expected: "%s", found "%s"'; + $data = [ + $expected, + $content, + ]; + $fix = $phpcsFile->addFixableError($error, $tag + 2, 'TagDescriptionSpacing', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($tag + 2, $expected); + } + } } diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 043f6700..d9e7fbe5 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -258,7 +258,7 @@ protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) * * @param File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. + * in the stack passed in $tokens. * @param int $commentStart The position in the stack where the comment started. * @return bool */ @@ -322,7 +322,7 @@ protected function hasInheritDocTag(File $phpcsFile, $stackPtr, $commentStart) * * @param File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. + * in the stack passed in $tokens. * @param int $commentStart The position in the stack where the comment started. * @return void */ diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index 145f300e..67958ca0 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -4,9 +4,8 @@ * * @see http://jdon.at/1h0wb * @see https://github.com/squizlabs/PHP_CodeSniffer/pull/1106 - * - * - added checks in annotations - * - added checks in return type (PHP 7.0+) + * - added checks in annotations + * - added checks in return type (PHP 7.0+) * * @todo remove once merged to squizlabs/PHP_CodeSniffer (?) */ diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index f07aa3e8..498d645d 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -6,11 +6,11 @@ * There is allowed more than one space after comma only in when this is multidimensional array. * * @todo: maybe we need fix part for multidimensional array, now it's checking for something like: - * [ - * [1, 3423, 342, 4324], - * [4432, 43, 4, 32], - * [22, 3432, 23, 4], - * ] + * [ + * [1, 3423, 342, 4324], + * [4432, 43, 4, 32], + * [22, 3432, 23, 4], + * ] */ namespace ZendCodingStandard\Sniffs\WhiteSpace; diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc b/test/Sniffs/Commenting/DocCommentUnitTest.inc index 438d98bf..bcf4e5c8 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc @@ -134,4 +134,56 @@ class Foo */ $x = 'something'; } + + /** @var string */ + private $b = 'xyz'; + + /** + * @param int $a + * @param string $b Description. + * @return void + * @throws \Exception + * @throws \RuntimeException When... + */ + public function test6($a, $b) + { + /** @var string $foo */ + $foo = 'foo'; + } + + /** + * Here is method description. + * It could be very long. + * There should be one empty line before params. + * @param int $a Another description. + * @param bool $b + * @param string $def This is very long + * description of the param + * ... continues here + * @return array This is + *description, of the returned value. + * + * @throws \Exception + * + * @throws \RuntimeException + * + * Here is an extra comment. It is not allowed to be here. + */ + public function test7($a, $b, $def) + { + return [$a, $b, $def]; + } + + /** + * @todo: comment + * next line + * another one + * + * @return void The description + * extra line here + * @dataProvider myDataProvider + * @noWhitespaceAfterTag*/ + public function test8() + { + } } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed index 1d05d675..0a2812a7 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed @@ -134,4 +134,58 @@ $c = 'xyz'; */ $x = 'something'; } + + /** @var string */ + private $b = 'xyz'; + + /** + * @param int $a + * @param string $b Description. + * @return void + * @throws \Exception + * @throws \RuntimeException When... + */ + public function test6($a, $b) + { + /** @var string $foo */ + $foo = 'foo'; + } + + /** + * Here is method description. + * It could be very long. + * There should be one empty line before params. + * + * @param int $a Another description. + * @param bool $b + * @param string $def This is very long + * description of the param + * ... continues here + * @return array This is + * description, of the returned value. + * + * @throws \Exception + * + * @throws \RuntimeException + * + * Here is an extra comment. It is not allowed to be here. + */ + public function test7($a, $b, $def) + { + return [$a, $b, $def]; + } + + /** + * @todo: comment + * next line + * another one + * + * @return void The description + * extra line here + * @dataProvider myDataProvider + * @noWhitespaceAfterTag + */ + public function test8() + { + } } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.php b/test/Sniffs/Commenting/DocCommentUnitTest.php index db7b4907..d1b49e00 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.php +++ b/test/Sniffs/Commenting/DocCommentUnitTest.php @@ -134,6 +134,22 @@ public function getErrorList($testFile = '') 111 => 1, 127 => 1, 133 => 1, + 138 => 1, + 142 => 2, + 143 => 2, + 145 => 2, + 146 => 2, + 150 => 2, + 158 => 2, + 161 => 1, + 162 => 1, + 164 => 1, + 170 => 1, + 179 => 1, + 180 => 1, + 183 => 1, + 184 => 1, + 185 => 1, ]; } From fb65d2e1bab443c0578d54e09521f3d62927e309 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 7 Sep 2017 08:27:46 +0100 Subject: [PATCH 138/225] Updated FunctionCommentSniff with latests PHP_CodeSniffer changes --- .../Commenting/FunctionCommentSniff.php | 388 +++++++++++------- 1 file changed, 238 insertions(+), 150 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index d9e7fbe5..3c1f7cc7 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -23,6 +23,7 @@ use function trim; use const PHP_VERSION_ID; +use const T_ANON_CLASS; use const T_CLOSURE; use const T_DOC_COMMENT_CLOSE_TAG; use const T_DOC_COMMENT_OPEN_TAG; @@ -35,6 +36,7 @@ use const T_STRING; use const T_WHITESPACE; use const T_YIELD; +use const T_YIELD_FROM; class FunctionCommentSniff extends PEARFunctionCommentSniff { @@ -105,8 +107,16 @@ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) $error = 'Return type missing for @return tag in function comment'; $phpcsFile->addError($error, $return, 'MissingReturnType'); } else { + // Support both a return type and a description. + preg_match('/^((?:\|?(?:array\([^\)]*\)|[\\\\a-z0-9\[\]]+))*)( .*)?/i', $content, $returnParts); + if (! isset($returnParts[1])) { + return; + } + + $returnType = $returnParts[1]; + // Check return type (can be multiple, separated by '|'). - $typeNames = explode('|', $content); + $typeNames = explode('|', $returnType); $suggestedNames = []; foreach ($typeNames as $i => $typeName) { $suggestedName = CodingStandard::suggestType($typeName); @@ -116,37 +126,41 @@ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) } $suggestedType = implode('|', $suggestedNames); - if ($content !== $suggestedType) { + if ($returnType !== $suggestedType) { $error = 'Expected "%s" but found "%s" for function return type'; $data = [ $suggestedType, - $content, + $returnType, ]; $fix = $phpcsFile->addFixableError($error, $return, 'InvalidReturn', $data); if ($fix) { - $phpcsFile->fixer->replaceToken($return + 2, $suggestedType); + $replacement = $suggestedType; + if (! empty($returnParts[2])) { + $replacement .= $returnParts[2]; + } + + $phpcsFile->fixer->replaceToken($return + 2, $replacement); + unset($replacement); } } - // Support both a return type and a description. The return type - // is anything up to the first space. - $returnParts = explode(' ', $content, 2); - $returnType = $returnParts[0]; - // If the return type is void, make sure there is // no return statement in the function. if ($returnType === 'void') { if (isset($tokens[$stackPtr]['scope_closer'])) { $endToken = $tokens[$stackPtr]['scope_closer']; for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) { - if ($tokens[$returnToken]['code'] === T_CLOSURE) { + if ($tokens[$returnToken]['code'] === T_CLOSURE + || $tokens[$returnToken]['code'] === T_ANON_CLASS + ) { $returnToken = $tokens[$returnToken]['scope_closer']; continue; } if ($tokens[$returnToken]['code'] === T_RETURN || $tokens[$returnToken]['code'] === T_YIELD + || $tokens[$returnToken]['code'] === T_YIELD_FROM ) { break; } @@ -162,19 +176,28 @@ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) } } } - } elseif ($returnType !== 'mixed') { - $returnTypes = explode('|', $returnType); - + } elseif ($returnType !== 'mixed' && ! in_array('void', $typeNames, true)) { // If return type is not void, there needs to be a return statement // somewhere in the function that returns something. - - // If "void" is not also in one of the return types. - if (! in_array('void', $returnTypes) - && isset($tokens[$stackPtr]['scope_closer']) - ) { + if (isset($tokens[$stackPtr]['scope_closer'])) { $endToken = $tokens[$stackPtr]['scope_closer']; - $returnToken = $phpcsFile->findNext([T_RETURN, T_YIELD], $stackPtr, $endToken); - if ($returnToken === false) { + for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) { + if ($tokens[$returnToken]['code'] === T_CLOSURE + || $tokens[$returnToken]['code'] === T_ANON_CLASS + ) { + $returnToken = $tokens[$returnToken]['scope_closer']; + continue; + } + + if ($tokens[$returnToken]['code'] === T_RETURN + || $tokens[$returnToken]['code'] === T_YIELD + || $tokens[$returnToken]['code'] === T_YIELD_FROM + ) { + break; + } + } + + if ($returnToken === $endToken) { $error = 'Function return type is not void, but function has no return statement'; $phpcsFile->addError($error, $return, 'InvalidNoReturn'); } else { @@ -254,7 +277,7 @@ protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) /** * Checks if function comment contains @inheritDoc tag. - * Methods should run only once. + * Method should run only once for each scope. * * @param File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token @@ -613,116 +636,101 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) // Check the param type value. $typeNames = explode('|', $param['type']); + $suggestedTypeNames = []; + foreach ($typeNames as $typeName) { $suggestedName = CodingStandard::suggestType($typeName); - if ($typeName !== $suggestedName) { - $error = 'Expected "%s" but found "%s" for parameter type'; - $data = [ - $suggestedName, - $typeName, - ]; - $fix = $phpcsFile->addFixableError($error, $param['tag'], 'IncorrectParamVarName', $data); + $suggestedTypeNames[] = $suggestedName; - if ($fix) { - $content = $suggestedName; - $content .= str_repeat(' ', $param['type_space']); - $content .= $param['var']; - $content .= str_repeat(' ', $param['var_space']); - if (isset($param['commentLines'][0])) { - $content .= $param['commentLines'][0]['comment']; - } + if (count($typeNames) > 1) { + continue; + } - $phpcsFile->fixer->replaceToken($param['tag'] + 2, $content); - } - } elseif (count($typeNames) === 1) { - // Check type hint for array and custom type. - $suggestedTypeHint = ''; - if (strpos($suggestedName, 'array') !== false || substr($suggestedName, -2) === '[]') { - $suggestedTypeHint = 'array'; - } elseif (strpos($suggestedName, 'callable') !== false) { - $suggestedTypeHint = 'callable'; - } elseif (strpos($suggestedName, 'callback') !== false) { - $suggestedTypeHint = 'callable'; - } elseif (! in_array($typeName, $this->simpleTypeHints, true)) { - $suggestedTypeHint = $suggestedName; - } elseif ($this->phpVersion >= 70000) { - if ($typeName === 'string') { - $suggestedTypeHint = 'string'; - } elseif ($typeName === 'int' || $typeName === 'integer') { - $suggestedTypeHint = 'int'; - } elseif ($typeName === 'float') { - $suggestedTypeHint = 'float'; - } elseif ($typeName === 'bool' || $typeName === 'boolean') { - $suggestedTypeHint = 'bool'; - } + // Check type hint for array and custom type. + $suggestedTypeHint = ''; + if (strpos($suggestedName, 'array') !== false || substr($suggestedName, -2) === '[]') { + $suggestedTypeHint = 'array'; + } elseif (strpos($suggestedName, 'callable') !== false) { + $suggestedTypeHint = 'callable'; + } elseif (strpos($suggestedName, 'callback') !== false) { + $suggestedTypeHint = 'callable'; + } elseif (! in_array($typeName, $this->simpleTypeHints, true)) { + $suggestedTypeHint = $suggestedName; + } + + if ($this->phpVersion >= 70000) { + if ($typeName === 'string') { + $suggestedTypeHint = 'string'; + } elseif ($typeName === 'int' || $typeName === 'integer') { + $suggestedTypeHint = 'int'; + } elseif ($typeName === 'float') { + $suggestedTypeHint = 'float'; + } elseif ($typeName === 'bool' || $typeName === 'boolean') { + $suggestedTypeHint = 'bool'; } + } - if ($suggestedTypeHint !== '' && isset($realParams[$pos])) { - $typeHint = $realParams[$pos]['type_hint']; - if ($typeHint === '') { - $error = 'Type hint "%s" missing for %s'; - $data = [ - $suggestedTypeHint, - $param['var'], - ]; - - $errorCode = 'TypeHintMissing'; - if ($suggestedTypeHint === 'string' - || $suggestedTypeHint === 'int' - || $suggestedTypeHint === 'float' - || $suggestedTypeHint === 'bool' - ) { - $errorCode = 'Scalar' . $errorCode; - } + if ($suggestedTypeHint !== '' && isset($realParams[$pos])) { + $typeHint = $realParams[$pos]['type_hint']; + if ($typeHint === '') { + $error = 'Type hint "%s" missing for %s'; + $data = [ + $suggestedTypeHint, + $param['var'], + ]; - $phpcsFile->addError($error, $stackPtr, $errorCode, $data); - } elseif ($typeHint !== substr($suggestedTypeHint, strlen($typeHint) * -1)) { - $error = 'Expected type hint "%s"; found "%s" for %s'; - $data = [ - $suggestedTypeHint, - $typeHint, - $param['var'], - ]; - $phpcsFile->addError($error, $stackPtr, 'IncorrectTypeHint', $data); - } - } elseif ($suggestedTypeHint === '' && isset($realParams[$pos])) { - $typeHint = $realParams[$pos]['type_hint']; - if ($typeHint !== '') { - $error = 'Unknown type hint "%s" found for %s'; - $data = [ - $typeHint, - $param['var'], - ]; - $phpcsFile->addError($error, $stackPtr, 'InvalidTypeHint', $data); + $errorCode = 'TypeHintMissing'; + if ($suggestedTypeHint === 'string' + || $suggestedTypeHint === 'int' + || $suggestedTypeHint === 'float' + || $suggestedTypeHint === 'bool' + ) { + $errorCode = 'Scalar' . $errorCode; } + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } elseif ($typeHint !== substr($suggestedTypeHint, strlen($typeHint) * -1)) { + $error = 'Expected type hint "%s"; found "%s" for %s'; + $data = [ + $suggestedTypeHint, + $typeHint, + $param['var'], + ]; + $phpcsFile->addError($error, $stackPtr, 'IncorrectTypeHint', $data); + } + } elseif ($suggestedTypeHint === '' && isset($realParams[$pos])) { + $typeHint = $realParams[$pos]['type_hint']; + if ($typeHint !== '') { + $error = 'Unknown type hint "%s" found for %s'; + $data = [ + $typeHint, + $param['var'], + ]; + $phpcsFile->addError($error, $stackPtr, 'InvalidTypeHint', $data); } } } - if ($param['var'] === '') { - continue; - } - - $foundParams[] = $param['var']; - - // Check number of spaces after the type. - $spaces = $maxType - strlen($param['type']) + 1; - if ($param['type_space'] !== $spaces) { - $error = 'Expected %s spaces after parameter type; %s found'; - $data = [ - $spaces, - $param['type_space'], + $suggestedType = implode($suggestedTypeNames, '|'); + if ($param['type'] !== $suggestedType) { + $error = 'Expected "%s" but found "%s" for parameter type'; + $data = [ + $suggestedType, + $param['type'], ]; - $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data); + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'IncorrectParamVarName', $data); if ($fix) { $phpcsFile->fixer->beginChangeset(); - $content = $param['type']; - $content .= str_repeat(' ', $spaces); + $content = $suggestedType; + $content .= str_repeat(' ', $param['type_space']); $content .= $param['var']; $content .= str_repeat(' ', $param['var_space']); - $content .= $param['commentLines'][0]['comment']; + if (isset($param['commentLines'][0])) { + $content .= $param['commentLines'][0]['comment']; + } + $phpcsFile->fixer->replaceToken($param['tag'] + 2, $content); // Fix up the indent of additional comment lines. @@ -733,7 +741,8 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) continue; } - $newIndent = $param['commentLines'][$lineNum]['indent'] + $spaces - $param['type_space']; + $diff = strlen($param['type']) - strlen($suggestedType); + $newIndent = $param['commentLines'][$lineNum]['indent'] - $diff; $phpcsFile->fixer->replaceToken( $param['commentLines'][$lineNum]['token'] - 1, str_repeat(' ', $newIndent) @@ -744,6 +753,15 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) } } + if ($param['var'] === '') { + continue; + } + + $foundParams[] = $param['var']; + + // Check number of spaces after the type. + $this->checkSpacingAfterParamType($phpcsFile, $param, $maxType); + // Make sure the param name is correct. if (isset($realParams[$pos])) { $realName = $realParams[$pos]['name']; @@ -775,43 +793,7 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) } // Check number of spaces after the var name. - $spaces = $maxVar - strlen($param['var']) + 1; - if ($param['var_space'] !== $spaces) { - $error = 'Expected %s spaces after parameter name; %s found'; - $data = [ - $spaces, - $param['var_space'], - ]; - $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data); - - if ($fix) { - $phpcsFile->fixer->beginChangeset(); - - $content = $param['type']; - $content .= str_repeat(' ', $param['type_space']); - $content .= $param['var']; - $content .= str_repeat(' ', $spaces); - $content .= $param['commentLines'][0]['comment']; - $phpcsFile->fixer->replaceToken($param['tag'] + 2, $content); - - // Fix up the indent of additional comment lines. - foreach ($param['commentLines'] as $lineNum => $line) { - if ($lineNum === 0 - || $param['commentLines'][$lineNum]['indent'] === 0 - ) { - continue; - } - - $newIndent = $param['commentLines'][$lineNum]['indent'] + $spaces - $param['var_space']; - $phpcsFile->fixer->replaceToken( - $param['commentLines'][$lineNum]['token'] - 1, - str_repeat(' ', $newIndent) - ); - } - - $phpcsFile->fixer->endChangeset(); - } - } + $this->checkSpacingAfterParamName($phpcsFile, $param, $maxVar); // Param comments must start with a capital letter and end with the full stop. if (preg_match('/^(\p{Ll}|\P{L})/u', $param['comment']) === 1) { @@ -843,4 +825,110 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) $phpcsFile->addError($error, $commentStart, 'MissingParamTag', $data); } } + + /** + * Check the spacing after the type of a parameter. + * + * @param File $phpcsFile The file being scanned. + * @param array $param The parameter to be checked. + * @param int $maxType The maxlength of the longest parameter type. + * @param int $spacing The number of spaces to add after the type. + */ + protected function checkSpacingAfterParamType(File $phpcsFile, array $param, $maxType, $spacing = 1) + { + // Check number of spaces after the type. + $spaces = $maxType - strlen($param['type']) + $spacing; + if ($param['type_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter type; %s found'; + $data = [ + $spaces, + $param['type_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + + $content = $param['type']; + $content .= str_repeat(' ', $spaces); + $content .= $param['var']; + $content .= str_repeat(' ', $param['var_space']); + $content .= $param['commentLines'][0]['comment']; + $phpcsFile->fixer->replaceToken($param['tag'] + 2, $content); + + // Fix up the indent of additional comment lines. + foreach ($param['commentLines'] as $lineNum => $line) { + if ($lineNum === 0 + || $param['commentLines'][$lineNum]['indent'] === 0 + ) { + continue; + } + + $diff = $param['type_space'] - $spaces; + $newIndent = $param['commentLines'][$lineNum]['indent'] - $diff; + $phpcsFile->fixer->replaceToken( + $param['commentLines'][$lineNum]['token'] - 1, + str_repeat(' ', $newIndent) + ); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + + /** + * Check the spacing after the name of a parameter. + * + * @param File $phpcsFile The file being scanned. + * @param array $param The parameter to be checked. + * @param int $maxVar The maxlength of the longest parameter name. + * @param int $spacing The number of spaces to add after the type. + */ + protected function checkSpacingAfterParamName(File $phpcsFile, array $param, $maxVar, $spacing = 1) + { + // Check number of spaces after the var name. + $spaces = $maxVar - strlen($param['var']) + $spacing; + if ($param['var_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter name; %s found'; + $data = [ + $spaces, + $param['var_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + + $content = $param['type']; + $content .= str_repeat(' ', $param['type_space']); + $content .= $param['var']; + $content .= str_repeat(' ', $spaces); + $content .= $param['commentLines'][0]['comment']; + $phpcsFile->fixer->replaceToken($param['tag'] + 2, $content); + + // Fix up the indent of additional comment lines. + foreach ($param['commentLines'] as $lineNum => $line) { + if ($lineNum === 0 + || $param['commentLines'][$lineNum]['indent'] === 0 + ) { + continue; + } + + $diff = $param['var_space'] - $spaces; + $newIndent = $param['commentLines'][$lineNum]['indent'] - $diff; + if ($newIndent <= 0) { + continue; + } + + $phpcsFile->fixer->replaceToken( + $param['commentLines'][$lineNum]['token'] - 1, + str_repeat(' ', $newIndent) + ); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } } From 3327dbcbaa1b8acb9ad0fd73326c76514fc7ad3d Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 11 Sep 2017 13:09:23 +0100 Subject: [PATCH 139/225] Added one more case to ScopeIndent sniff and simplified checks --- .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 67 +++---------------- .../Sniffs/WhiteSpace/ScopeIndentUnitTest.inc | 23 +++++++ .../WhiteSpace/ScopeIndentUnitTest.inc.fixed | 23 +++++++ 3 files changed, 55 insertions(+), 58 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index d0a89ad5..11f1864b 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -544,42 +544,6 @@ public function process(File $phpcsFile, $stackPtr) } } - // one less indent - // if it is in control structure - // and there is no eol between - // open and close parenthesis - if (($tokens[$next]['code'] === T_CLOSE_PARENTHESIS - || $tokens[$next]['code'] === T_CLOSE_SHORT_ARRAY - || ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET - && isset($tokens[$next]['scope_opener']))) - && ($controlStructurePtr = $this->getControlStructurePtr($phpcsFile, $next)) - && $tokens[$next]['line'] < $tokens[$tokens[$controlStructurePtr]['parenthesis_closer']]['line'] - && ! $this->hasContainNewLine( - $phpcsFile, - $tokens[$controlStructurePtr]['parenthesis_opener'], - $tokens[$controlStructurePtr]['parenthesis_closer'] - ) - ) { - // if it is closure, so $next token is T_CLOSE_PARENTHESIS - // and the following non-empty token is T_CURLY_OPEN_BRACKET - // then expect one more indent on the whole body of the closure. - if ($tokens[$next]['code'] === T_CLOSE_PARENTHESIS - && ($fNext = $phpcsFile->findNext(Tokens::$emptyTokens, $next + 1, null, true)) - && $tokens[$fNext]['code'] === T_OPEN_CURLY_BRACKET - && isset($tokens[$fNext]['scope_closer']) - ) { - $extraIndent -= $this->indent; - $sc = $tokens[$fNext]['scope_closer']; - if (isset($extras[$sc])) { - $extras[$sc] -= $this->indent; - } else { - $extras[$sc] = - $this->indent; - } - } else { - $expectedIndent -= $this->indent; - } - } - $expectedIndent += $extraIndent; $previousIndent = $expectedIndent; @@ -649,8 +613,8 @@ public function process(File $phpcsFile, $stackPtr) } $xEnd = $tokens[$i][$key]; - // no extra indent if closing parenthesis/bracket is in the same line - if ($tokens[$i]['line'] === $tokens[$xEnd]['line']) { + // no extra indent if there is no new line between open and close brackets + if (! $this->hasContainNewLine($phpcsFile, $i, $xEnd)) { continue; } @@ -708,28 +672,15 @@ public function process(File $phpcsFile, $stackPtr) ++$firstInNextLine; } - // Additional indent of the content if it should be one more depth. - // We count them only if it is not in the same line as control structure - // or the closing parenthesis of the statement is not in the line with - // closing parenthesis of control structure. $ei1 = 0; - $controlStructurePtr = $this->getControlStructurePtr($phpcsFile, $i); - if ($controlStructurePtr === false - || $this->hasContainNewLine( - $phpcsFile, - $tokens[$controlStructurePtr]['parenthesis_opener'], - $tokens[$controlStructurePtr]['parenthesis_closer'] - ) + if ($tokens[$first]['level'] === $tokens[$firstInNextLine]['level'] + && $tokens[$firstInNextLine]['code'] !== T_CLOSE_CURLY_BRACKET ) { - if ($tokens[$first]['level'] === $tokens[$firstInNextLine]['level'] - && $tokens[$firstInNextLine]['code'] !== T_CLOSE_CURLY_BRACKET - ) { - $ei1 = $this->indent; - if (isset($extras[$xEnd])) { - $extras[$xEnd] += $ei1; - } else { - $extras[$xEnd] = $ei1; - } + $ei1 = $this->indent; + if (isset($extras[$xEnd])) { + $extras[$xEnd] += $ei1; + } else { + $extras[$xEnd] = $ei1; } } diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc index d6f1a8ac..1de8625f 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc @@ -477,3 +477,26 @@ get_class($value) 'foo' => 'bar', 'bar' => 'baz', ]); + +function test1(array $a, $b) +{ + if (array_filter($a, function ($v) use ($b) { + return $v === $b * 2; + })) { + return 1; + } + + return 0; +} + +function test2() +{ + if (false === strpos( + 'haystack', + 'needle' + )) { + return 1; + } + + return 0; +} diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed index be31a841..ff686179 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed @@ -475,3 +475,26 @@ throw new MyException(sprintf( 'foo' => 'bar', 'bar' => 'baz', ]); + +function test1(array $a, $b) +{ + if (array_filter($a, function ($v) use ($b) { + return $v === $b * 2; + })) { + return 1; + } + + return 0; +} + +function test2() +{ + if (false === strpos( + 'haystack', + 'needle' + )) { + return 1; + } + + return 0; +} From 24930ffa950dd36eb63986dda582983011994ff1 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 17:50:44 +0100 Subject: [PATCH 140/225] DocComment sniff - property tagWithType is public It is possible to change these tags in ruleset. --- src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index 5e99e4b3..a933f0a5 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -34,7 +34,7 @@ class DocCommentSniff implements Sniff { public $indent = 4; - private $tagWithType = [ + public $tagWithType = [ '@var', '@param', '@return', From 601b54b33b0c79250b9829c993a377e190ff12c9 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 17:52:56 +0100 Subject: [PATCH 141/225] DocComment sniff - remove empty lines in doc comments Adds * in there is an empty line in comment. If there is more then one line with only * it will be reduced just to one. --- .../Sniffs/Commenting/DocCommentSniff.php | 22 +++++++++++++++++++ test/Sniffs/Commenting/DocCommentUnitTest.inc | 9 ++++++++ .../Commenting/DocCommentUnitTest.inc.fixed | 9 ++++++++ test/Sniffs/Commenting/DocCommentUnitTest.php | 1 + 4 files changed, 41 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index a933f0a5..28b2f5df 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -557,6 +557,28 @@ private function checkBlankLinesInComment(File $phpcsFile, $commentStart, $comme $from = $next; } + + // Check for blank lines without * + $from = $commentStart; + $to = $commentEnd; + + while ($next = $phpcsFile->findNext(T_DOC_COMMENT_WHITESPACE, $from + 1, $to + 1, true)) { + if ($tokens[$next]['line'] > $tokens[$from]['line'] + 1) { + $ptr = $from + 1; + while ($tokens[$ptr]['line'] === $tokens[$from]['line']) { + ++$ptr; + } + + $error = 'Blank line found in PHPDoc comment'; + $fix = $phpcsFile->addFixableError($error, $ptr, 'BlankLine'); + + if ($fix) { + $phpcsFile->fixer->addContentBefore($ptr, '*'); + } + } + + $from = $next; + } } /** diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc b/test/Sniffs/Commenting/DocCommentUnitTest.inc index bcf4e5c8..3296bca9 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc @@ -186,4 +186,13 @@ class Foo public function test8() { } + + /** + * Empty line in the comment is not allowed. + + * Here is something else. + */ + public function test9() + { + } } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed index 0a2812a7..c56fe5bb 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed @@ -188,4 +188,13 @@ $c = 'xyz'; public function test8() { } + + /** + * Empty line in the comment is not allowed. + * + * Here is something else. + */ + public function test9() + { + } } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.php b/test/Sniffs/Commenting/DocCommentUnitTest.php index d1b49e00..5e8be254 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.php +++ b/test/Sniffs/Commenting/DocCommentUnitTest.php @@ -150,6 +150,7 @@ public function getErrorList($testFile = '') 183 => 1, 184 => 1, 185 => 1, + 192 => 1, ]; } From dfc1e08efe6a97d01b296b6d89c631f2b9785f9e Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 17:54:47 +0100 Subject: [PATCH 142/225] Fixed typo in method name --- .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index a2801975..e64c2301 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -283,7 +283,7 @@ private function checkTag(File $phpcsFile, $stackPtr) $newTypesArr = []; foreach ($typesArr as $type) { - $expected = $this->getExcepctedName($phpcsFile, $type, $stackPtr + 2); + $expected = $this->getExpectedName($phpcsFile, $type, $stackPtr + 2); $newTypesArr[] = $expected; } @@ -315,7 +315,7 @@ private function checkTag(File $phpcsFile, $stackPtr) * @param int $stackPtr * @return string */ - private function getExcepctedName(File $phpcsFile, $class, $stackPtr) + private function getExpectedName(File $phpcsFile, $class, $stackPtr) { if ($class[0] === '\\') { $result = $this->hasDifferentCase(ltrim($class, '\\')); From 1220a248b962de980552231dc254d39152d5f96a Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 18:02:13 +0100 Subject: [PATCH 143/225] Extracted namespace helper methods to internal trait --- src/ZendCodingStandard/Helper/Namespaces.php | 204 ++++++++++++++++++ .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 67 +----- .../PHP/ImportInternalConstantSniff.php | 81 +------ .../PHP/ImportInternalFunctionSniff.php | 81 +------ 4 files changed, 215 insertions(+), 218 deletions(-) create mode 100644 src/ZendCodingStandard/Helper/Namespaces.php diff --git a/src/ZendCodingStandard/Helper/Namespaces.php b/src/ZendCodingStandard/Helper/Namespaces.php new file mode 100644 index 00000000..a3abfe03 --- /dev/null +++ b/src/ZendCodingStandard/Helper/Namespaces.php @@ -0,0 +1,204 @@ +findPrevious(T_NAMESPACE, $stackPtr - 1)) { + $nsEnd = $phpcsFile->findNext([T_NS_SEPARATOR, T_STRING, T_WHITESPACE], $nsStart + 1, null, true); + return trim($phpcsFile->getTokensAsString($nsStart + 1, $nsEnd - $nsStart - 1)); + } + + return ''; + } + + /** + * Returns array of imported classes. Key is lowercase name, and value is FQCN. + * + * @param int $stackPtr + * @return string[][] + */ + private function getGlobalUses(File $phpcsFile, $stackPtr = 0) + { + $first = 0; + $last = $phpcsFile->numTokens; + + $tokens = $phpcsFile->getTokens(); + + $nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr); + if ($nsStart && isset($tokens[$nsStart]['scope_opener'])) { + $first = $tokens[$nsStart]['scope_opener']; + $last = $tokens[$nsStart]['scope_closer']; + } + + $imports = []; + + $use = $first; + while ($use = $phpcsFile->findNext(T_USE, $use + 1, $last)) { + if (! empty($tokens[$use]['conditions'])) { + continue; + } + + $nextToken = $phpcsFile->findNext(T_WHITESPACE, $use + 1, null, true); + + $end = $phpcsFile->findNext( + [T_NS_SEPARATOR, T_STRING], + $nextToken + 1, + null, + true + ); + + $class = trim($phpcsFile->getTokensAsString($nextToken, $end - $nextToken)); + + $endOfStatement = $phpcsFile->findEndOfStatement($use); + if ($aliasStart = $phpcsFile->findNext([T_WHITESPACE, T_AS], $end + 1, $endOfStatement, true)) { + $alias = trim($phpcsFile->getTokensAsString($aliasStart, $endOfStatement - $aliasStart)); + } else { + if (strrchr($class, '\\') !== false) { + $alias = substr(strrchr($class, '\\'), 1); + } else { + $alias = $class; + } + } + + $imports[strtolower($alias)] = ['alias' => $alias, 'class' => $class]; + } + + return $imports; + } + + /** + * @param int $stackPtr + * @param null|int $lastUse + * @return string[][] + */ + private function getImportedConstants(File $phpcsFile, $stackPtr, &$lastUse) + { + $first = 0; + $last = $phpcsFile->numTokens; + + $tokens = $phpcsFile->getTokens(); + + $nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr); + if ($nsStart && isset($tokens[$nsStart]['scope_opener'])) { + $first = $tokens[$nsStart]['scope_opener']; + $last = $tokens[$nsStart]['scope_closer']; + } + + $lastUse = null; + $constants = []; + + $use = $first; + while ($use = $phpcsFile->findNext(T_USE, $use + 1, $last)) { + if (CodingStandard::isGlobalUse($phpcsFile, $use)) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $use + 1, null, true); + if ($tokens[$next]['code'] === T_STRING + && strtolower($tokens[$next]['content']) === 'const' + ) { + $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); + $end = $phpcsFile->findPrevious( + T_STRING, + $phpcsFile->findNext([T_AS, T_SEMICOLON], $start + 1) - 1 + ); + $endOfStatement = $phpcsFile->findEndOfStatement($next); + $name = $phpcsFile->findPrevious(T_STRING, $endOfStatement - 1); + $fullName = $phpcsFile->getTokensAsString($start, $end - $start + 1); + + $constants[strtoupper($tokens[$name]['content'])] = [ + 'name' => $tokens[$name]['content'], + 'fqn' => ltrim($fullName, '\\'), + ]; + + $lastUse = $use; + } + } + + if (! $lastUse) { + $lastUse = $use; + } + } + + return $constants; + } + + /** + * @param int $stackPtr + * @param null|int $lastUse + * @return string[][] + */ + private function getImportedFunctions(File $phpcsFile, $stackPtr, &$lastUse) + { + $first = 0; + $last = $phpcsFile->numTokens; + + $tokens = $phpcsFile->getTokens(); + + $nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr); + if ($nsStart && isset($tokens[$nsStart]['scope_opener'])) { + $first = $tokens[$nsStart]['scope_opener']; + $last = $tokens[$nsStart]['scope_closer']; + } + + $lastUse = null; + $functions = []; + + $use = $first; + while ($use = $phpcsFile->findNext(T_USE, $use + 1, $last)) { + if (CodingStandard::isGlobalUse($phpcsFile, $use)) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $use + 1, null, true); + if ($tokens[$next]['code'] === T_STRING + && strtolower($tokens[$next]['content']) === 'function' + ) { + $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); + $end = $phpcsFile->findPrevious( + T_STRING, + $phpcsFile->findNext([T_AS, T_SEMICOLON], $start + 1) - 1 + ); + $endOfStatement = $phpcsFile->findEndOfStatement($next); + $name = $phpcsFile->findPrevious(T_STRING, $endOfStatement - 1); + $fullName = $phpcsFile->getTokensAsString($start, $end - $start + 1); + + $functions[strtolower($tokens[$name]['content'])] = [ + 'name' => $tokens[$name]['content'], + 'fqn' => ltrim($fullName, '\\'), + ]; + + $lastUse = $use; + } + } + + if (! $lastUse) { + $lastUse = $use; + } + } + + return $functions; + } +} diff --git a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index e64c2301..14db0fbc 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -4,6 +4,7 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use ZendCodingStandard\Helper\Namespaces; use function array_map; use function array_merge; @@ -18,12 +19,10 @@ use function preg_quote; use function preg_replace; use function strlen; -use function strrchr; use function strtolower; use function substr; use function trim; -use const T_AS; use const T_CLOSURE; use const T_COLON; use const T_COMMA; @@ -34,7 +33,6 @@ use const T_EXTENDS; use const T_FUNCTION; use const T_IMPLEMENTS; -use const T_NAMESPACE; use const T_NEW; use const T_NS_SEPARATOR; use const T_NULLABLE; @@ -54,6 +52,8 @@ */ class CorrectClassNameCaseSniff implements Sniff { + use Namespaces; + /** * @var array */ @@ -456,52 +456,6 @@ private function error(File $phpcsFile, $start, $end, $expected, $actual) } } - /** - * Returns array of imported classes. Key is lowercase name, and value is FQCN. - * - * @param File $phpcsFile - * @return array - */ - private function getGlobalUses(File $phpcsFile) - { - $tokens = $phpcsFile->getTokens(); - - $imports = []; - - $use = 0; - while ($use = $phpcsFile->findNext(T_USE, $use + 1)) { - if (! empty($tokens[$use]['conditions'])) { - continue; - } - - $nextToken = $phpcsFile->findNext(T_WHITESPACE, $use + 1, null, true); - - $end = $phpcsFile->findNext( - [T_NS_SEPARATOR, T_STRING], - $nextToken + 1, - null, - true - ); - - $class = trim($phpcsFile->getTokensAsString($nextToken, $end - $nextToken)); - - $endOfStatement = $phpcsFile->findEndOfStatement($use); - if ($aliasStart = $phpcsFile->findNext([T_WHITESPACE, T_AS], $end + 1, $endOfStatement, true)) { - $alias = trim($phpcsFile->getTokensAsString($aliasStart, $endOfStatement - $aliasStart)); - } else { - if (strrchr($class, '\\') !== false) { - $alias = substr(strrchr($class, '\\'), 1); - } else { - $alias = $class; - } - } - - $imports[strtolower($alias)] = ['alias' => $alias, 'class' => $class]; - } - - return $imports; - } - /** * Checks if class is defined and has different case - then returns class name * with correct case. Otherwise returns false. @@ -525,19 +479,4 @@ private function hasDifferentCase($class) return $this->declaredClasses[$index]; } - - /** - * @param File $phpcsFile - * @param int $stackPtr - * @return string - */ - private function getNamespace(File $phpcsFile, $stackPtr) - { - if ($nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr - 1)) { - $nsEnd = $phpcsFile->findNext([T_NS_SEPARATOR, T_STRING, T_WHITESPACE], $nsStart + 1, null, true); - return trim($phpcsFile->getTokensAsString($nsStart + 1, $nsEnd - $nsStart - 1)); - } - - return ''; - } } diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php index aec17db2..a49fe9ef 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php @@ -4,17 +4,14 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; -use ZendCodingStandard\CodingStandard; +use ZendCodingStandard\Helper\Namespaces; use function array_walk_recursive; use function get_defined_constants; -use function ltrim; use function sprintf; use function strtolower; use function strtoupper; -use function trim; -use const T_AS; use const T_BITWISE_AND; use const T_DOUBLE_COLON; use const T_FUNCTION; @@ -24,13 +21,12 @@ use const T_OBJECT_OPERATOR; use const T_OPEN_PARENTHESIS; use const T_OPEN_TAG; -use const T_SEMICOLON; use const T_STRING; -use const T_USE; -use const T_WHITESPACE; class ImportInternalConstantSniff implements Sniff { + use Namespaces; + /** * @var array Hash map of all php built in constant names. */ @@ -91,7 +87,7 @@ public function process(File $phpcsFile, $stackPtr) $namespace = $this->getNamespace($phpcsFile, $stackPtr); if ($this->currentNamespace !== $namespace) { $this->currentNamespace = $namespace; - $this->importedConstants = $this->getImportedConstants($phpcsFile, $stackPtr); + $this->importedConstants = $this->getImportedConstants($phpcsFile, $stackPtr, $this->lastUse); } $tokens = $phpcsFile->getTokens(); @@ -170,75 +166,6 @@ public function process(File $phpcsFile, $stackPtr) } } - /** - * @param File $phpcsFile - * @param int $stackPtr - * @return string - */ - private function getNamespace(File $phpcsFile, $stackPtr) - { - if ($nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr - 1)) { - $nsEnd = $phpcsFile->findNext([T_NS_SEPARATOR, T_STRING, T_WHITESPACE], $nsStart + 1, null, true); - return trim($phpcsFile->getTokensAsString($nsStart + 1, $nsEnd - $nsStart - 1)); - } - - return ''; - } - - /** - * @param File $phpcsFile - * @param int $stackPtr - * @return array - */ - private function getImportedConstants(File $phpcsFile, $stackPtr) - { - $first = 0; - $last = $phpcsFile->numTokens; - - $tokens = $phpcsFile->getTokens(); - - $nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr); - if ($nsStart && isset($tokens[$nsStart]['scope_opener'])) { - $first = $tokens[$nsStart]['scope_opener']; - $last = $tokens[$nsStart]['scope_closer']; - } - - $this->lastUse = null; - $constants = []; - - $use = $first; - while ($use = $phpcsFile->findNext(T_USE, $use + 1, $last)) { - if (CodingStandard::isGlobalUse($phpcsFile, $use)) { - $next = $phpcsFile->findNext(Tokens::$emptyTokens, $use + 1, null, true); - if ($tokens[$next]['code'] === T_STRING - && strtolower($tokens[$next]['content']) === 'const' - ) { - $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); - $end = $phpcsFile->findPrevious( - T_STRING, - $phpcsFile->findNext([T_AS, T_SEMICOLON], $start + 1) - 1 - ); - $endOfStatement = $phpcsFile->findEndOfStatement($next); - $name = $phpcsFile->findPrevious(T_STRING, $endOfStatement - 1); - $fullName = $phpcsFile->getTokensAsString($start, $end - $start + 1); - - $constants[strtoupper($tokens[$name]['content'])] = [ - 'name' => $tokens[$name]['content'], - 'fqn' => ltrim($fullName, '\\'), - ]; - - $this->lastUse = $use; - } - } - - if (! $this->lastUse) { - $this->lastUse = $use; - } - } - - return $constants; - } - /** * @param File $phpcsFile * @param int $stackPtr diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php index 5f645eec..4c1fdf08 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php @@ -4,16 +4,13 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; -use ZendCodingStandard\CodingStandard; +use ZendCodingStandard\Helper\Namespaces; use function array_flip; use function get_defined_functions; -use function ltrim; use function sprintf; use function strtolower; -use function trim; -use const T_AS; use const T_BITWISE_AND; use const T_DOUBLE_COLON; use const T_FUNCTION; @@ -23,13 +20,12 @@ use const T_OBJECT_OPERATOR; use const T_OPEN_PARENTHESIS; use const T_OPEN_TAG; -use const T_SEMICOLON; use const T_STRING; -use const T_USE; -use const T_WHITESPACE; class ImportInternalFunctionSniff implements Sniff { + use Namespaces; + /** * @var array Hash map of all php built in function names. */ @@ -82,7 +78,7 @@ public function process(File $phpcsFile, $stackPtr) $namespace = $this->getNamespace($phpcsFile, $stackPtr); if ($this->currentNamespace !== $namespace) { $this->currentNamespace = $namespace; - $this->importedFunctions = $this->getImportedFunctions($phpcsFile, $stackPtr); + $this->importedFunctions = $this->getImportedFunctions($phpcsFile, $stackPtr, $this->lastUse); } $tokens = $phpcsFile->getTokens(); @@ -158,75 +154,6 @@ public function process(File $phpcsFile, $stackPtr) } } - /** - * @param File $phpcsFile - * @param int $stackPtr - * @return string - */ - private function getNamespace(File $phpcsFile, $stackPtr) - { - if ($nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr - 1)) { - $nsEnd = $phpcsFile->findNext([T_NS_SEPARATOR, T_STRING, T_WHITESPACE], $nsStart + 1, null, true); - return trim($phpcsFile->getTokensAsString($nsStart + 1, $nsEnd - $nsStart - 1)); - } - - return ''; - } - - /** - * @param File $phpcsFile - * @param int $stackPtr - * @return array - */ - private function getImportedFunctions(File $phpcsFile, $stackPtr) - { - $first = 0; - $last = $phpcsFile->numTokens; - - $tokens = $phpcsFile->getTokens(); - - $nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr); - if ($nsStart && isset($tokens[$nsStart]['scope_opener'])) { - $first = $tokens[$nsStart]['scope_opener']; - $last = $tokens[$nsStart]['scope_closer']; - } - - $this->lastUse = null; - $functions = []; - - $use = $first; - while ($use = $phpcsFile->findNext(T_USE, $use + 1, $last)) { - if (CodingStandard::isGlobalUse($phpcsFile, $use)) { - $next = $phpcsFile->findNext(Tokens::$emptyTokens, $use + 1, null, true); - if ($tokens[$next]['code'] === T_STRING - && strtolower($tokens[$next]['content']) === 'function' - ) { - $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); - $end = $phpcsFile->findPrevious( - T_STRING, - $phpcsFile->findNext([T_AS, T_SEMICOLON], $start + 1) - 1 - ); - $endOfStatement = $phpcsFile->findEndOfStatement($next); - $name = $phpcsFile->findPrevious(T_STRING, $endOfStatement - 1); - $fullName = $phpcsFile->getTokensAsString($start, $end - $start + 1); - - $functions[strtolower($tokens[$name]['content'])] = [ - 'name' => $tokens[$name]['content'], - 'fqn' => ltrim($fullName, '\\'), - ]; - - $this->lastUse = $use; - } - } - - if (! $this->lastUse) { - $this->lastUse = $use; - } - } - - return $functions; - } - /** * @param File $phpcsFile * @param int $stackPtr From 92817e3a3a66707f342a1b4e56f87013dbe50ef5 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 18:29:17 +0100 Subject: [PATCH 144/225] Added custom sniffs for function tags - `@param` are required only when parameter needs specification or parameter type hint is not given - `@return` is required only when there is no return type declared or return type needs specification (array, iterable, \Traversable) (if function returns void, return tag can must be omitted) - `@throws` should be defined for each explicitly thrown exception in the method --- src/ZendCodingStandard/Helper/Methods.php | 414 +++++++ .../Commenting/FunctionCommentSniff.php | 976 +++------------ .../Sniffs/Functions/ParamSniff.php | 688 +++++++++++ .../Sniffs/Functions/ReturnTypeSniff.php | 1057 +++++++++++++++++ .../Sniffs/Functions/ThrowsSniff.php | 327 +++++ src/ZendCodingStandard/ruleset.xml | 11 - .../Commenting/FunctionCommentUnitTest.1.inc | 71 -- .../FunctionCommentUnitTest.1.inc.fixed | 76 -- .../Commenting/FunctionCommentUnitTest.inc | 71 +- .../FunctionCommentUnitTest.inc.fixed | 67 +- .../Commenting/FunctionCommentUnitTest.php | 37 +- test/Sniffs/Functions/ParamUnitTest.inc | 304 +++++ test/Sniffs/Functions/ParamUnitTest.inc.fixed | 310 +++++ test/Sniffs/Functions/ParamUnitTest.php | 110 ++ .../Sniffs/Functions/ReturnTypeUnitTest.1.inc | 403 +++++++ .../Sniffs/Functions/ReturnTypeUnitTest.2.inc | 473 ++++++++ test/Sniffs/Functions/ReturnTypeUnitTest.inc | 300 +++++ test/Sniffs/Functions/ReturnTypeUnitTest.php | 237 ++++ test/Sniffs/Functions/ThrowsUnitTest.inc | 273 +++++ test/Sniffs/Functions/ThrowsUnitTest.php | 42 + 20 files changed, 5161 insertions(+), 1086 deletions(-) create mode 100644 src/ZendCodingStandard/Helper/Methods.php create mode 100644 src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php create mode 100644 src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php create mode 100644 src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php delete mode 100644 test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc delete mode 100644 test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc.fixed create mode 100644 test/Sniffs/Functions/ParamUnitTest.inc create mode 100644 test/Sniffs/Functions/ParamUnitTest.inc.fixed create mode 100644 test/Sniffs/Functions/ParamUnitTest.php create mode 100644 test/Sniffs/Functions/ReturnTypeUnitTest.1.inc create mode 100644 test/Sniffs/Functions/ReturnTypeUnitTest.2.inc create mode 100644 test/Sniffs/Functions/ReturnTypeUnitTest.inc create mode 100644 test/Sniffs/Functions/ReturnTypeUnitTest.php create mode 100644 test/Sniffs/Functions/ThrowsUnitTest.inc create mode 100644 test/Sniffs/Functions/ThrowsUnitTest.php diff --git a/src/ZendCodingStandard/Helper/Methods.php b/src/ZendCodingStandard/Helper/Methods.php new file mode 100644 index 00000000..a1457a5c --- /dev/null +++ b/src/ZendCodingStandard/Helper/Methods.php @@ -0,0 +1,414 @@ +currentFile !== $phpcsFile) { + $this->currentFile = $phpcsFile; + $this->currentNamespace = null; + } + + $namespace = $this->getNamespace($phpcsFile, $stackPtr); + if ($this->currentNamespace !== $namespace) { + $this->currentNamespace = $namespace; + $this->importedClasses = $this->getGlobalUses($phpcsFile, $stackPtr); + } + + $tokens = $phpcsFile->getTokens(); + + $this->methodName = $phpcsFile->getDeclarationName($stackPtr); + $this->isSpecialMethod = $this->methodName === '__construct' || $this->methodName === '__destruct'; + + // Get class name of the method, name of the parent class and implemented interfaces names + $this->className = null; + $this->parentClassName = null; + $this->implementedInterfaceNames = []; + if ($tokens[$stackPtr]['conditions']) { + $conditionCode = end($tokens[$stackPtr]['conditions']); + if (in_array($conditionCode, [T_CLASS, T_TRAIT, T_INTERFACE], true)) { + $conditionPtr = key($tokens[$stackPtr]['conditions']); + $this->className = $phpcsFile->getDeclarationName($conditionPtr); + $this->parentClassName = $phpcsFile->findExtendedClassName($conditionPtr) ?: null; + $this->implementedInterfaceNames = $phpcsFile->findImplementedInterfaceNames($conditionPtr) ?: []; + } + } + } + + /** + * @param string $a + * @param string $b + * @return int + */ + public function sortTypes($a, $b) + { + $a = strtolower(str_replace('\\', ':', $a)); + $b = strtolower(str_replace('\\', ':', $b)); + + if ($a === 'null' || strpos($a, 'null[') === 0) { + return -1; + } + + if ($b === 'null' || strpos($b, 'null[') === 0) { + return 1; + } + + if ($a === 'true' || $a === 'false') { + return -1; + } + + if ($b === 'true' || $b === 'false') { + return 1; + } + + $aIsSimple = array_filter($this->simpleReturnTypes, function ($v) use ($a) { + return $v === $a || strpos($a, $v . '[') === 0; + }); + $bIsSimple = array_filter($this->simpleReturnTypes, function ($v) use ($b) { + return $v === $b || strpos($b, $v . '[') === 0; + }); + + if ($aIsSimple && $bIsSimple) { + return strcmp($a, $b); + } + + if ($aIsSimple) { + return -1; + } + + if ($bIsSimple) { + return 1; + } + + return strcmp( + preg_replace('/^:/', '', $a), + preg_replace('/^:/', '', $b) + ); + } + + /** + * @param string $class + * @return string + */ + private function getSuggestedType($class) + { + $prefix = $class[0] === '?' ? '?' : ''; + $suffix = strstr($class, '['); + $clear = strtolower(strtr($class, ['?' => '', '[' => '', ']' => ''])); + + if (in_array($clear, $this->simpleReturnTypes, true)) { + return $prefix . $clear . $suffix; + } + + $suggested = CodingStandard::suggestType($clear); + if ($suggested !== $clear) { + return $prefix . $suggested . $suffix; + } + + // Is it a current class? + if ($this->isClassName($clear)) { + return $prefix . 'self' . $suffix; + } + + // Is it a parent class? + if ($this->isParentClassName($clear)) { + return $prefix . 'parent' . $suffix; + } + + // Is the class imported? + if (isset($this->importedClasses[$clear])) { + return $prefix . $this->importedClasses[$clear]['alias'] . $suffix; + } + + if ($clear[0] === '\\') { + $ltrim = ltrim($clear, '\\'); + foreach ($this->importedClasses as $use) { + if (strtolower($use['class']) === $ltrim) { + return $prefix . $use['alias'] . $suffix; + } + } + } + + return $class; + } + + /** + * @param string $typeHint + * @param string $typeStr + * @return bool + */ + private function typesMatch($typeHint, $typeStr) + { + $isNullable = $typeHint[0] === '?'; + $lowerTypeHint = strtolower($isNullable ? substr($typeHint, 1) : $typeHint); + $lowerTypeStr = strtolower($typeStr); + + $types = explode('|', $lowerTypeStr); + $count = count($types); + + // For nullable types we expect null and type in PHPDocs + if ($isNullable && $count !== 2) { + return false; + } + + // If type is not nullable PHPDocs should just containt type name + if (! $isNullable && $count !== 1) { + return false; + } + + $fqcnTypeHint = strtolower($this->getFQCN($lowerTypeHint)); + foreach ($types as $key => $type) { + if ($type === 'null') { + continue; + } + + $types[$key] = strtolower($this->getFQCN($type)); + } + $fqcnTypes = implode('|', $types); + + return $fqcnTypeHint === $fqcnTypes + || ($isNullable + && ('null|' . $fqcnTypeHint === $fqcnTypes + || $fqcnTypeHint . '|null' === $fqcnTypes)); + } + + /** + * @param string $class + * @return string + */ + private function getFQCN($class) + { + // It is a simple type + if (in_array(strtolower($class), $this->simpleReturnTypes, true)) { + return $class; + } + + // It is already FQCN + if ($class[0] === '\\') { + return $class; + } + + // It is an imported class + if (isset($this->importedClasses[$class])) { + return '\\' . $this->importedClasses[$class]['class']; + } + + // It is a class from the current namespace + return ($this->currentNamespace ? '\\' . $this->currentNamespace : '') . '\\' . $class; + } + + /** + * @param string $name + * @return bool + */ + private function isClassName($name) + { + if (! $this->className) { + return false; + } + + $ns = strtolower($this->currentNamespace); + $lowerClassName = strtolower($this->className); + $lowerFQCN = ($ns ? '\\' . $ns : '') . '\\' . $lowerClassName; + $lower = strtolower($name); + + return $lower === $lowerFQCN + || $lower === $lowerClassName; + } + + /** + * @param string $name + * @return bool + */ + private function isParentClassName($name) + { + if (! $this->parentClassName) { + return false; + } + + $lowerParentClassName = strtolower($this->parentClassName); + $lowerFQCN = strtolower($this->getFQCN($lowerParentClassName)); + $lower = strtolower($name); + + return $lower === $lowerFQCN + || $lower === $lowerParentClassName; + } + + /** + * @param int $tagPtr + */ + private function removeTag(File $phpcsFile, $tagPtr) + { + $tokens = $phpcsFile->getTokens(); + + $phpcsFile->fixer->beginChangeset(); + if ($tokens[$tagPtr - 1]['code'] === T_DOC_COMMENT_WHITESPACE + && $tokens[$tagPtr + 3]['code'] === T_DOC_COMMENT_WHITESPACE + ) { + $phpcsFile->fixer->replaceToken($tagPtr - 1, ''); + } + + $phpcsFile->fixer->replaceToken($tagPtr, ''); + $phpcsFile->fixer->replaceToken($tagPtr + 1, ''); + $phpcsFile->fixer->replaceToken($tagPtr + 2, ''); + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param int $stackPtr + * @return null|int + */ + private function getCommentStart(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $skip = Tokens::$methodPrefixes + + [T_WHITESPACE => T_WHITESPACE]; + + $commentEnd = $phpcsFile->findPrevious($skip, $stackPtr - 1, null, true); + // There is no doc-comment for the function. + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG) { + return null; + } + + return $tokens[$commentEnd]['comment_opener']; + } +} diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 3c1f7cc7..b1994f51 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -1,933 +1,239 @@ getTokens(); - - // Skip constructor and destructor. - $methodName = $phpcsFile->getDeclarationName($stackPtr); - $isSpecialMethod = $methodName === '__construct' || $methodName === '__destruct'; - - $return = null; - foreach ($tokens[$commentStart]['comment_tags'] as $tag) { - if ($tokens[$tag]['content'] === '@return') { - if ($return !== null) { - $error = 'Only 1 @return tag is allowed in a function comment'; - $phpcsFile->addError($error, $tag, 'DuplicateReturn'); - return; - } - - $return = $tag; - } - } - - if ($isSpecialMethod === true) { - return; - } - - if ($return !== null) { - $content = $tokens[$return + 2]['content']; - if (empty($content) || $tokens[$return + 2]['code'] !== T_DOC_COMMENT_STRING) { - $error = 'Return type missing for @return tag in function comment'; - $phpcsFile->addError($error, $return, 'MissingReturnType'); - } else { - // Support both a return type and a description. - preg_match('/^((?:\|?(?:array\([^\)]*\)|[\\\\a-z0-9\[\]]+))*)( .*)?/i', $content, $returnParts); - if (! isset($returnParts[1])) { - return; - } - - $returnType = $returnParts[1]; - - // Check return type (can be multiple, separated by '|'). - $typeNames = explode('|', $returnType); - $suggestedNames = []; - foreach ($typeNames as $i => $typeName) { - $suggestedName = CodingStandard::suggestType($typeName); - if (! in_array($suggestedName, $suggestedNames)) { - $suggestedNames[] = $suggestedName; - } - } - - $suggestedType = implode('|', $suggestedNames); - if ($returnType !== $suggestedType) { - $error = 'Expected "%s" but found "%s" for function return type'; - $data = [ - $suggestedType, - $returnType, - ]; - $fix = $phpcsFile->addFixableError($error, $return, 'InvalidReturn', $data); - - if ($fix) { - $replacement = $suggestedType; - if (! empty($returnParts[2])) { - $replacement .= $returnParts[2]; - } - - $phpcsFile->fixer->replaceToken($return + 2, $replacement); - unset($replacement); - } - } - - // If the return type is void, make sure there is - // no return statement in the function. - if ($returnType === 'void') { - if (isset($tokens[$stackPtr]['scope_closer'])) { - $endToken = $tokens[$stackPtr]['scope_closer']; - for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) { - if ($tokens[$returnToken]['code'] === T_CLOSURE - || $tokens[$returnToken]['code'] === T_ANON_CLASS - ) { - $returnToken = $tokens[$returnToken]['scope_closer']; - continue; - } - - if ($tokens[$returnToken]['code'] === T_RETURN - || $tokens[$returnToken]['code'] === T_YIELD - || $tokens[$returnToken]['code'] === T_YIELD_FROM - ) { - break; - } - } - - if ($returnToken !== $endToken) { - // If the function is not returning anything, just - // exiting, then there is no problem. - $semicolon = $phpcsFile->findNext(T_WHITESPACE, $returnToken + 1, null, true); - if ($tokens[$semicolon]['code'] !== T_SEMICOLON) { - $error = 'Function return type is void, but function contains return statement'; - $phpcsFile->addError($error, $return, 'InvalidReturnVoid'); - } - } - } - } elseif ($returnType !== 'mixed' && ! in_array('void', $typeNames, true)) { - // If return type is not void, there needs to be a return statement - // somewhere in the function that returns something. - if (isset($tokens[$stackPtr]['scope_closer'])) { - $endToken = $tokens[$stackPtr]['scope_closer']; - for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) { - if ($tokens[$returnToken]['code'] === T_CLOSURE - || $tokens[$returnToken]['code'] === T_ANON_CLASS - ) { - $returnToken = $tokens[$returnToken]['scope_closer']; - continue; - } - - if ($tokens[$returnToken]['code'] === T_RETURN - || $tokens[$returnToken]['code'] === T_YIELD - || $tokens[$returnToken]['code'] === T_YIELD_FROM - ) { - break; - } - } - - if ($returnToken === $endToken) { - $error = 'Function return type is not void, but function has no return statement'; - $phpcsFile->addError($error, $return, 'InvalidNoReturn'); - } else { - $semicolon = $phpcsFile->findNext(T_WHITESPACE, $returnToken + 1, null, true); - if ($tokens[$semicolon]['code'] === T_SEMICOLON) { - $error = 'Function return type is not void, but function is returning void here'; - $phpcsFile->addError($error, $returnToken, 'InvalidReturnNotVoid'); - } - } - } - } - } - } elseif (! $this->hasInheritDocTag($phpcsFile, $stackPtr, $commentStart)) { - $error = 'Missing @return tag in function comment'; - $phpcsFile->addError($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn'); - } + return [T_FUNCTION]; } /** - * @inheritDoc + * @param int $stackPtr */ - protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) + public function process(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); + $skip = Tokens::$methodPrefixes + + [T_WHITESPACE => T_WHITESPACE]; - foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { - if ($tokens[$tag]['content'] !== '@throws') { - continue; - } + $commentEnd = $phpcsFile->findPrevious($skip, $stackPtr - 1, null, true); + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $error = 'You must use "/**" style comments for a function comment'; + $phpcsFile->addError($error, $stackPtr, 'WrongStyle'); + return; + } - $exception = null; - $comment = null; - if ($tokens[$tag + 2]['code'] === T_DOC_COMMENT_STRING) { - $matches = []; - preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[$tag + 2]['content'], $matches); - $exception = $matches[1]; - if (isset($matches[2]) && trim($matches[2]) !== '') { - $comment = $matches[2]; - } + $commentStart = null; + if ($tokens[$commentEnd]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + if ($tokens[$commentEnd]['line'] !== $tokens[$stackPtr]['line'] - 1) { + $error = 'There must be no blank lines after the function comment'; + $phpcsFile->addError($error, $commentEnd, 'SpacingAfter'); } - if ($exception === null) { - $error = 'Exception type and comment missing for @throws tag in function comment'; - $phpcsFile->addError($error, $tag, 'InvalidThrows'); - } elseif ($comment === null) { - $error = 'Comment missing for @throws tag in function comment'; - $phpcsFile->addError($error, $tag, 'EmptyThrows'); - } else { - // Any strings until the next tag belong to this comment. - if (isset($tokens[$commentStart]['comment_tags'][$pos + 1])) { - $end = $tokens[$commentStart]['comment_tags'][$pos + 1]; - } else { - $end = $tokens[$commentStart]['comment_closer']; - } + $commentStart = $tokens[$commentEnd]['comment_opener']; - for ($i = $tag + 3; $i < $end; $i++) { - if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { - $comment .= ' ' . $tokens[$i]['content']; - } - } - - // Starts with a capital letter and ends with a fullstop. - $firstChar = $comment{0}; - if (strtoupper($firstChar) !== $firstChar) { - $error = '@throws tag comment must start with a capital letter'; - $phpcsFile->addError($error, $tag + 2, 'ThrowsNotCapital'); - } - - $lastChar = substr($comment, -1); - if ($lastChar !== '.') { - $error = '@throws tag comment must end with a full stop'; - $phpcsFile->addError($error, $tag + 2, 'ThrowsNoFullStop'); - } - } + $this->processSee($phpcsFile, $commentStart, $commentEnd); + $this->processTagOrder($phpcsFile, $commentStart); } } /** - * Checks if function comment contains @inheritDoc tag. - * Method should run only once for each scope. - * - * @param File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. - * @param int $commentStart The position in the stack where the comment started. - * @return bool + * @param int $commentStart + * @param int $commentEnd */ - protected function hasInheritDocTag(File $phpcsFile, $stackPtr, $commentStart) + private function processSee(File $phpcsFile, $commentStart, $commentEnd) { - $id = spl_object_hash($phpcsFile) . ':' . $stackPtr; - - if (isset($this->hasInheritDoc[$id])) { - return $this->hasInheritDoc[$id]; - } - $tokens = $phpcsFile->getTokens(); - $commentEnd = $tokens[$commentStart]['comment_closer']; - $commentContent = $phpcsFile->getTokensAsString($commentStart + 1, $commentEnd - $commentStart - 1); - - if (preg_match('/\*.*\{(@inheritDoc)\}/i', $commentContent, $m)) { - if ($m[1] !== '@inheritDoc') { - $data = ['@inheritDoc', $m[1]]; - $error = 'Expected {%s}, found {%s}.'; - $fix = $phpcsFile->addFixableError($error, $commentStart, 'InheritDocCase', $data); - - if ($fix) { - $newCommentContent = str_replace('{' . $m[1] . '}', '{@inheritDoc}', $commentContent); - $phpcsFile->fixer->beginChangeset(); - for ($i = $commentStart + 1; $i < $commentEnd; ++$i) { - $phpcsFile->fixer->replaceToken($i, ''); - } - $phpcsFile->fixer->addContent($commentStart + 1, $newCommentContent); - $phpcsFile->fixer->endChangeset(); - } + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if (strtolower($tokens[$tag]['content']) !== '@see') { + continue; } - $this->hasInheritDoc[$id] = true; - return $this->hasInheritDoc[$id]; - } - - foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { - if (strtolower($tokens[$tag]['content']) === '@inheritdoc') { - if ($tokens[$tag]['content'] !== '@inheritDoc') { - $data = ['@inheritDoc', $tokens[$tag]['content']]; - $error = 'Expected %s, found %s.'; - $fix = $phpcsFile->addFixableError($error, $tag, 'InheritDocCase', $data); - - if ($fix) { - $phpcsFile->fixer->replaceToken($tag, '@inheritDoc'); - } - } - - $this->hasInheritDoc[$id] = true; - return $this->hasInheritDoc[$id]; + // Make sure the tag isn't empty. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if (! $string || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for @see tag in function comment'; + $phpcsFile->addError($error, $tag, 'EmptySees'); } } - - $this->hasInheritDoc[$id] = false; - return $this->hasInheritDoc[$id]; } /** - * Process the @dataProvider tag of test's functions. - * - * @param File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. - * @param int $commentStart The position in the stack where the comment started. - * @return void + * @param int $commentStart */ - protected function processDataProvider(File $phpcsFile, $stackPtr, $commentStart) + private function processTagOrder(File $phpcsFile, $commentStart) { $tokens = $phpcsFile->getTokens(); - $tags = $tokens[$commentStart]['comment_tags']; - // Checks @dataProvider tags - foreach ($tags as $pos => $tag) { - if (strtolower($tokens[$tag]['content']) !== '@dataprovider') { - continue; - } - - // Check if method name starts from "test". - $functionPtr = $phpcsFile->findNext(T_FUNCTION, $tag + 1); - $namePtr = $phpcsFile->findNext(T_STRING, $functionPtr + 1); - $functionName = $tokens[$namePtr]['content']; - - if (strpos($functionName, 'test') !== 0) { - $error = 'Tag @dataProvider is allowed only for test* methods.'; - $phpcsFile->addError($error, $tag, 'DataProviderTestMethod'); - } + $tags = $tokens[$commentStart]['comment_tags']; - // Check if data provider name is given and does not have "Provider" suffix. - if ($tokens[$tag + 1]['code'] !== T_DOC_COMMENT_WHITESPACE - || $tokens[$tag + 2]['code'] !== T_DOC_COMMENT_STRING - ) { - $error = 'Missing data provider name.'; - $phpcsFile->addError($error, $tag, 'DataProviderMissing'); + $data = []; + foreach ($tags as $key => $tag) { + if (isset($tags[$key + 1])) { + $lastFrom = $tags[$key + 1]; } else { - $providerName = $tokens[$tag + 2]['content']; - - if (preg_match('/Provider$/', $providerName)) { - $error = 'Data provider name should have "Provider" suffix.'; - $phpcsFile->addError($error, $tag, 'DataProviderInvalidName'); - } + $lastFrom = $tokens[$commentStart]['comment_closer']; } - // Check if @dataProvider tag is above @param tag(s). - for ($i = $pos - 1; $i >= 0; --$i) { - $prevTag = $tags[$i]; - if (strtolower($tokens[$prevTag]['content']) === '@param') { - $error = 'Tag @dataProvider must be above @param tag(s).'; - $fix = $phpcsFile->addFixableError($error, $tag, 'DataProviderNotAboveParams'); - - if ($fix) { - $first = $last = $tag; - while ($tokens[$first]['line'] === $tokens[$tag]['line']) { - --$first; - } - while ($tokens[$last]['line'] === $tokens[$tag]['line']) { - ++$last; - } - $content = $phpcsFile->getTokensAsString($first + 1, $last - $first - 1); - - $prevLine = $prevTag; - while ($tokens[$prevLine]['line'] === $tokens[$prevTag]['line']) { - --$prevLine; - } - - $phpcsFile->fixer->beginChangeset(); - for ($j = $first + 1; $j < $last; ++$j) { - $phpcsFile->fixer->replaceToken($j, ''); - } - $phpcsFile->fixer->addContent($prevLine, $content); - $phpcsFile->fixer->endChangeset(); - } - - continue 2; - } - } - - if ($tokens[$tag]['content'] !== '@dataProvider') { - $data = ['@dataProvider', $tokens[$tag]['content']]; - $error = 'Expected %s, found %s'; - $fix = $phpcsFile->addFixableError($error, $tag, 'DataProviderInvalidCase', $data); - - if ($fix) { - $phpcsFile->fixer->replaceToken($tag, '@dataProvider'); - } + $last = $phpcsFile->findPrevious( + [T_DOC_COMMENT_STAR, T_DOC_COMMENT_WHITESPACE], + $lastFrom - 1, + null, + true + ); + while ($tokens[$last + 1]['line'] === $tokens[$last]['line']) { + ++$last; } - $star = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $tag - 1); - $indent = ''; - $prevLine = $star; - while ($tokens[$prevLine]['line'] === $tokens[$tag]['line']) { - if ($tokens[$prevLine]['code'] === T_DOC_COMMENT_WHITESPACE) { - $indent = $tokens[$prevLine]['content']; - break; - } - --$prevLine; - } + $data[] = [ + 'tag' => strtolower($tokens[$tag]['content']), + 'token' => $tag, + 'first' => $phpcsFile->findFirstOnLine([], $tag, true), + 'last' => $last, + ]; + } - // Find non-empty token before @dataProvider tag. - $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR], $tag - 1, null, true); - if ($tokens[$prev]['code'] !== T_DOC_COMMENT_OPEN_TAG - && $tokens[$prev]['line'] === $tokens[$tag]['line'] - 1 - ) { - if (! isset($tags[$pos - 1]) - || strtolower($tokens[$tags[$pos - 1]]['content']) !== '@dataprovider' - ) { - $error = 'Missing blank line before @dataProvider tag.'; - $fix = $phpcsFile->addFixableError($error, $tag, 'DataProviderBlankLineBefore'); + $firstTag = current($data); - if ($fix) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->addNewline($prev); - $phpcsFile->fixer->addContent($prev, $indent . '*'); - $phpcsFile->fixer->endChangeset(); - } - } - } elseif ($tokens[$prev]['line'] < $tokens[$tag]['line'] - 1 - && isset($tags[$pos - 1]) - && strtolower($tokens[$tags[$pos - 1]]['content']) === '@dataprovider' - ) { - $error = 'Empty line between @dataProvider tags is not allowed.'; - $fix = $phpcsFile->addFixableError($error, $tag, 'DataProviderNoEmptyLineBetween'); + // Sorts values only and keep unchanged keys. + uasort($data, function (array $a, array $b) use ($data) { + $ai = array_search($a['tag'], $this->tagOrder, true); + $bi = array_search($b['tag'], $this->tagOrder, true); - if ($fix) { - $phpcsFile->fixer->beginChangeset(); - for ($i = $tag; $i > $prev + 1; --$i) { - if ($tokens[$i]['line'] === $tokens[$tag]['line']) { - continue; - } - - $phpcsFile->fixer->replaceToken($i, ''); - } - $phpcsFile->fixer->endChangeset(); - } - } - - // Find first token in next line. - $nextLine = $tag; - while ($tokens[$nextLine]['line'] === $tokens[$tag]['line']) { - ++$nextLine; + if ($ai !== false && $bi !== false && $ai !== $bi) { + return $ai > $bi ? 1 : -1; } - // Find non-empty token starting from next line. - $next = $phpcsFile->findNext([T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR], $nextLine, null, true); - if ($tokens[$next]['line'] === $tokens[$tag]['line'] + 1 - && $tokens[$next]['code'] !== T_DOC_COMMENT_CLOSE_TAG - ) { - if (! isset($tags[$pos + 1]) - || $next !== $tags[$pos + 1] - || strtolower($tokens[$next]['content']) !== '@dataprovider' - ) { - $error = 'Missing blank line after @dataProvider tag.'; - $fix = $phpcsFile->addFixableError($error, $tag, 'DataProviderBlankLineAfter'); - - if ($fix) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->addNewlineBefore($nextLine); - $phpcsFile->fixer->addContent($nextLine - 1, $indent . '*'); - $phpcsFile->fixer->endChangeset(); - } - } + if ($ai !== false && $bi === false) { + return 1; } - } - } - /** - * @inheritDoc - */ - protected function processParams(File $phpcsFile, $stackPtr, $commentStart) - { - if (! $this->phpVersion) { - $this->phpVersion = Config::getConfigData('php_version'); - if (! $this->phpVersion) { - $this->phpVersion = PHP_VERSION_ID; + if ($ai === false && $bi !== false) { + return -1; } - } - $this->processDataProvider($phpcsFile, $stackPtr, $commentStart); - $tokens = $phpcsFile->getTokens(); + return array_search($a, $data, true) > array_search($b, $data, true) ? 1 : -1; + }); - $params = []; - $maxType = 0; - $maxVar = 0; - foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { - if ($tokens[$tag]['content'] !== '@param') { + $last = key($data); + foreach ($data as $key => $val) { + if ($last <= $key) { + $last = $key; continue; } - $type = ''; - $typeSpace = 0; - $var = ''; - $varSpace = 0; - $comment = ''; - $commentLines = []; - if ($tokens[$tag + 2]['code'] === T_DOC_COMMENT_STRING) { - $matches = []; - preg_match( - '/([^$&.]+)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', - $tokens[$tag + 2]['content'], - $matches - ); - - if (! empty($matches)) { - $typeLen = strlen($matches[1]); - $type = trim($matches[1]); - $typeSpace = $typeLen - strlen($type); - $typeLen = strlen($type); - if ($typeLen > $maxType) { - $maxType = $typeLen; - } - } - - if (isset($matches[2])) { - $var = $matches[2]; - $varLen = strlen($var); - if ($varLen > $maxVar) { - $maxVar = $varLen; - } - - if (isset($matches[4])) { - $varSpace = strlen($matches[3]); - $comment = $matches[4]; - $commentLines[] = [ - 'comment' => $comment, - 'token' => $tag + 2, - 'indent' => $varSpace, - ]; - - // Any strings until the next tag belong to this comment. - if (isset($tokens[$commentStart]['comment_tags'][$pos + 1])) { - $end = $tokens[$commentStart]['comment_tags'][$pos + 1]; - } else { - $end = $tokens[$commentStart]['comment_closer']; - } - - for ($i = $tag + 3; $i < $end; $i++) { - if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { - $indent = 0; - if ($tokens[$i - 1]['code'] === T_DOC_COMMENT_WHITESPACE) { - $indent = strlen($tokens[$i - 1]['content']); - } + $error = 'Tags are ordered incorrectly. Here is the first in wrong order'; + $fix = $phpcsFile->addFixableError($error, $val['token'], 'InvalidOrder'); - $comment .= ' ' . $tokens[$i]['content']; - $commentLines[] = [ - 'comment' => $tokens[$i]['content'], - 'token' => $i, - 'indent' => $indent, - ]; - } - } - } else { - $error = 'Missing parameter comment'; - $phpcsFile->addError($error, $tag, 'MissingParamComment'); - $commentLines[] = ['comment' => '']; + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $toAdd = []; + foreach ($data as $k => $v) { + $toAdd[] = $phpcsFile->getTokensAsString($v['first'], $v['last'] - $v['first'] + 1); + for ($i = $v['first']; $i <= $v['last']; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); } - } else { - $error = 'Missing parameter name'; - $phpcsFile->addError($error, $tag, 'MissingParamName'); } - } else { - $error = 'Missing parameter type'; - $phpcsFile->addError($error, $tag, 'MissingParamType'); - } - - $params[] = [ - 'tag' => $tag, - 'type' => $type, - 'var' => $var, - 'comment' => $comment, - 'commentLines' => $commentLines, - 'type_space' => $typeSpace, - 'var_space' => $varSpace, - ]; - } - - $realParams = $phpcsFile->getMethodParameters($stackPtr); - $foundParams = []; - - // We want to use ... for all variable length arguments, so added - // this prefix to the variable name so comparisons are easier. - foreach ($realParams as $pos => $param) { - if ($param['variable_length'] === true) { - $realParams[$pos]['name'] = '...' . $realParams[$pos]['name']; + foreach ($toAdd as $content) { + $phpcsFile->fixer->addContent($firstTag['first'], $content); + } + $phpcsFile->fixer->endChangeset(); } + return; } - foreach ($params as $pos => $param) { - // If the type is empty, the whole line is empty. - if ($param['type'] === '') { + // If order is correct check empty lines between tags. + $skip = [T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR]; + foreach ($tags as $key => $tag) { + // Skip the first tag. Empty line after description is added in other sniff. + if ($key === 0) { continue; } - // Check the param type value. - $typeNames = explode('|', $param['type']); - $suggestedTypeNames = []; - - foreach ($typeNames as $typeName) { - $suggestedName = CodingStandard::suggestType($typeName); - $suggestedTypeNames[] = $suggestedName; - - if (count($typeNames) > 1) { - continue; - } - - // Check type hint for array and custom type. - $suggestedTypeHint = ''; - if (strpos($suggestedName, 'array') !== false || substr($suggestedName, -2) === '[]') { - $suggestedTypeHint = 'array'; - } elseif (strpos($suggestedName, 'callable') !== false) { - $suggestedTypeHint = 'callable'; - } elseif (strpos($suggestedName, 'callback') !== false) { - $suggestedTypeHint = 'callable'; - } elseif (! in_array($typeName, $this->simpleTypeHints, true)) { - $suggestedTypeHint = $suggestedName; - } - - if ($this->phpVersion >= 70000) { - if ($typeName === 'string') { - $suggestedTypeHint = 'string'; - } elseif ($typeName === 'int' || $typeName === 'integer') { - $suggestedTypeHint = 'int'; - } elseif ($typeName === 'float') { - $suggestedTypeHint = 'float'; - } elseif ($typeName === 'bool' || $typeName === 'boolean') { - $suggestedTypeHint = 'bool'; - } - } - - if ($suggestedTypeHint !== '' && isset($realParams[$pos])) { - $typeHint = $realParams[$pos]['type_hint']; - if ($typeHint === '') { - $error = 'Type hint "%s" missing for %s'; - $data = [ - $suggestedTypeHint, - $param['var'], - ]; - - $errorCode = 'TypeHintMissing'; - if ($suggestedTypeHint === 'string' - || $suggestedTypeHint === 'int' - || $suggestedTypeHint === 'float' - || $suggestedTypeHint === 'bool' - ) { - $errorCode = 'Scalar' . $errorCode; - } - - $phpcsFile->addError($error, $stackPtr, $errorCode, $data); - } elseif ($typeHint !== substr($suggestedTypeHint, strlen($typeHint) * -1)) { - $error = 'Expected type hint "%s"; found "%s" for %s'; - $data = [ - $suggestedTypeHint, - $typeHint, - $param['var'], - ]; - $phpcsFile->addError($error, $stackPtr, 'IncorrectTypeHint', $data); - } - } elseif ($suggestedTypeHint === '' && isset($realParams[$pos])) { - $typeHint = $realParams[$pos]['type_hint']; - if ($typeHint !== '') { - $error = 'Unknown type hint "%s" found for %s'; - $data = [ - $typeHint, - $param['var'], - ]; - $phpcsFile->addError($error, $stackPtr, 'InvalidTypeHint', $data); - } - } + $prevTag = $tags[$key - 1]; + if (in_array($tokens[$tag]['content'], $this->blankLineBefore, true) + && $tokens[$prevTag]['content'] !== $tokens[$tag]['content'] + ) { + $expected = 1; + } else { + $expected = 0; } - $suggestedType = implode($suggestedTypeNames, '|'); - if ($param['type'] !== $suggestedType) { - $error = 'Expected "%s" but found "%s" for parameter type'; - $data = [ - $suggestedType, - $param['type'], + $prev = $phpcsFile->findPrevious($skip, $tag - 1, null, true); + $found = $tokens[$tag]['line'] - $tokens[$prev]['line'] - 1; + if ($found !== $expected) { + $error = 'Invalid number of empty lines between tags; expected %d, but found %d'; + $data = [ + $expected, + $found, ]; + $fix = $phpcsFile->addFixableError($error, $prev + 2, 'BlankLine', $data); - $fix = $phpcsFile->addFixableError($error, $param['tag'], 'IncorrectParamVarName', $data); if ($fix) { - $phpcsFile->fixer->beginChangeset(); - - $content = $suggestedType; - $content .= str_repeat(' ', $param['type_space']); - $content .= $param['var']; - $content .= str_repeat(' ', $param['var_space']); - if (isset($param['commentLines'][0])) { - $content .= $param['commentLines'][0]['comment']; - } + if ($found > $expected) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $prev + 1; $i < $tag; ++$i) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_WHITESPACE + && strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false + ) { + if ($found === $expected) { + break; + } - $phpcsFile->fixer->replaceToken($param['tag'] + 2, $content); + --$found; + } - // Fix up the indent of additional comment lines. - foreach ($param['commentLines'] as $lineNum => $line) { - if ($lineNum === 0 - || $param['commentLines'][$lineNum]['indent'] === 0 - ) { - continue; + $phpcsFile->fixer->replaceToken($i, ''); } - - $diff = strlen($param['type']) - strlen($suggestedType); - $newIndent = $param['commentLines'][$lineNum]['indent'] - $diff; - $phpcsFile->fixer->replaceToken( - $param['commentLines'][$lineNum]['token'] - 1, - str_repeat(' ', $newIndent) - ); - } - - $phpcsFile->fixer->endChangeset(); - } - } - - if ($param['var'] === '') { - continue; - } - - $foundParams[] = $param['var']; - - // Check number of spaces after the type. - $this->checkSpacingAfterParamType($phpcsFile, $param, $maxType); - - // Make sure the param name is correct. - if (isset($realParams[$pos])) { - $realName = $realParams[$pos]['name']; - if ($realName !== $param['var']) { - $code = 'ParamNameNoMatch'; - $data = [ - $param['var'], - $realName, - ]; - - $error = 'Doc comment for parameter %s does not match '; - if (strtolower($param['var']) === strtolower($realName)) { - $error .= 'case of '; - $code = 'ParamNameNoCaseMatch'; - } - - $error .= 'actual variable name %s'; - - $phpcsFile->addError($error, $param['tag'], $code, $data); - } - } elseif (substr($param['var'], -4) !== ',...') { - // We must have an extra parameter comment. - $error = 'Superfluous parameter comment'; - $phpcsFile->addError($error, $param['tag'], 'ExtraParamComment'); - } - - if ($param['comment'] === '') { - continue; - } - - // Check number of spaces after the var name. - $this->checkSpacingAfterParamName($phpcsFile, $param, $maxVar); - - // Param comments must start with a capital letter and end with the full stop. - if (preg_match('/^(\p{Ll}|\P{L})/u', $param['comment']) === 1) { - $error = 'Parameter comment must start with a capital letter'; - $phpcsFile->addError($error, $param['tag'], 'ParamCommentNotCapital'); - } - - $lastChar = substr($param['comment'], -1); - if ($lastChar !== '.') { - $error = 'Parameter comment must end with a full stop'; - $phpcsFile->addError($error, $param['tag'], 'ParamCommentFullStop'); - } - } - - if ($this->hasInheritDocTag($phpcsFile, $stackPtr, $commentStart)) { - return; - } - - $realNames = []; - foreach ($realParams as $realParam) { - $realNames[] = $realParam['name']; - } - - // Report missing comments. - $diff = array_diff($realNames, $foundParams); - foreach ($diff as $neededParam) { - $error = 'Doc comment for parameter "%s" missing'; - $data = [$neededParam]; - $phpcsFile->addError($error, $commentStart, 'MissingParamTag', $data); - } - } - - /** - * Check the spacing after the type of a parameter. - * - * @param File $phpcsFile The file being scanned. - * @param array $param The parameter to be checked. - * @param int $maxType The maxlength of the longest parameter type. - * @param int $spacing The number of spaces to add after the type. - */ - protected function checkSpacingAfterParamType(File $phpcsFile, array $param, $maxType, $spacing = 1) - { - // Check number of spaces after the type. - $spaces = $maxType - strlen($param['type']) + $spacing; - if ($param['type_space'] !== $spaces) { - $error = 'Expected %s spaces after parameter type; %s found'; - $data = [ - $spaces, - $param['type_space'], - ]; - - $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data); - if ($fix) { - $phpcsFile->fixer->beginChangeset(); - - $content = $param['type']; - $content .= str_repeat(' ', $spaces); - $content .= $param['var']; - $content .= str_repeat(' ', $param['var_space']); - $content .= $param['commentLines'][0]['comment']; - $phpcsFile->fixer->replaceToken($param['tag'] + 2, $content); - - // Fix up the indent of additional comment lines. - foreach ($param['commentLines'] as $lineNum => $line) { - if ($lineNum === 0 - || $param['commentLines'][$lineNum]['indent'] === 0 - ) { - continue; - } - - $diff = $param['type_space'] - $spaces; - $newIndent = $param['commentLines'][$lineNum]['indent'] - $diff; - $phpcsFile->fixer->replaceToken( - $param['commentLines'][$lineNum]['token'] - 1, - str_repeat(' ', $newIndent) - ); - } - - $phpcsFile->fixer->endChangeset(); - } - } - } - - /** - * Check the spacing after the name of a parameter. - * - * @param File $phpcsFile The file being scanned. - * @param array $param The parameter to be checked. - * @param int $maxVar The maxlength of the longest parameter name. - * @param int $spacing The number of spaces to add after the type. - */ - protected function checkSpacingAfterParamName(File $phpcsFile, array $param, $maxVar, $spacing = 1) - { - // Check number of spaces after the var name. - $spaces = $maxVar - strlen($param['var']) + $spacing; - if ($param['var_space'] !== $spaces) { - $error = 'Expected %s spaces after parameter name; %s found'; - $data = [ - $spaces, - $param['var_space'], - ]; - - $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data); - if ($fix) { - $phpcsFile->fixer->beginChangeset(); - - $content = $param['type']; - $content .= str_repeat(' ', $param['type_space']); - $content .= $param['var']; - $content .= str_repeat(' ', $spaces); - $content .= $param['commentLines'][0]['comment']; - $phpcsFile->fixer->replaceToken($param['tag'] + 2, $content); - - // Fix up the indent of additional comment lines. - foreach ($param['commentLines'] as $lineNum => $line) { - if ($lineNum === 0 - || $param['commentLines'][$lineNum]['indent'] === 0 - ) { - continue; - } - - $diff = $param['var_space'] - $spaces; - $newIndent = $param['commentLines'][$lineNum]['indent'] - $diff; - if ($newIndent <= 0) { - continue; + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->addContent($prev, $phpcsFile->eolChar . '*'); } - - $phpcsFile->fixer->replaceToken( - $param['commentLines'][$lineNum]['token'] - 1, - str_repeat(' ', $newIndent) - ); } - - $phpcsFile->fixer->endChangeset(); } } } diff --git a/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php new file mode 100644 index 00000000..29ee83ef --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php @@ -0,0 +1,688 @@ +initScope($phpcsFile, $stackPtr); + + $this->processedParams = []; + $this->params = $phpcsFile->getMethodParameters($stackPtr); + + if ($commentStart = $this->getCommentStart($phpcsFile, $stackPtr)) { + $this->processParamDoc($phpcsFile, $stackPtr, $commentStart); + } + $this->processParamSpec($phpcsFile, $stackPtr); + } + + /** + * @param int $stackPtr + * @param int $commentStart + */ + private function processParamDoc(File $phpcsFile, $stackPtr, $commentStart) + { + $params = []; + $paramsMap = []; + $tokens = $phpcsFile->getTokens(); + + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if (strtolower($tokens[$tag]['content']) !== '@param') { + continue; + } + + if ($tokens[$tag + 2]['code'] !== T_DOC_COMMENT_STRING) { + $error = 'Param type ane name missing for @param tag in function comment'; + $phpcsFile->addError($error, $tag, 'MissingParamDetailsDoc'); + + continue; + } + + $split = preg_split('/\s/', $tokens[$tag + 2]['content'], 3); + + if (! isset($split[1])) { + if ($this->isVariable($split[0])) { + $error = 'Missing param type for param %s'; + $data = [ + $split[0], + ]; + $phpcsFile->addError($error, $tag + 2, 'MissingParamTypeDoc', $data); + } else { + $error = 'Missing parameter name in PHPDOcs'; + $phpcsFile->addError($error, $tag + 2, 'MissingParamNameDoc'); + } + + continue; + } + + if (! $this->isVariable($split[1])) { + $error = 'Invalid parameter name'; + $phpcsFile->addError($error, $tag + 2, 'InvalidParamNameDoc'); + continue; + } + $name = $split[1]; + + $clearName = strtolower(str_replace('.', '', $name)); + if (in_array($clearName, $params, true)) { + $error = 'Param tag is duplicated for parameter %s'; + $data = [ + $name, + ]; + $phpcsFile->addError($error, $tag + 2, 'DuplicatedParamTag', $data); + continue; + } + $params[] = $clearName; + + $param = array_filter($this->params, function (array $param) use ($clearName) { + return strtolower($param['name']) === $clearName; + }); + + if (! $param) { + $error = 'Parameter %s has not been found in function declaration'; + $data = [ + $name, + ]; + $phpcsFile->addError($error, $tag + 2, 'NoParameter', $data); + continue; + } + + // Add param to processed list, even if it may not be checked. + $this->processedParams[] = key($param); + $paramsMap[key($param)] = ['token' => $tag, 'name' => $name]; + + if (! $this->isType($split[0])) { + $error = 'Invalid type for param %s'; + $data = [ + $split[1], + ]; + $phpcsFile->addError($error, $tag + 2, 'InvalidParamTypeDoc', $data); + continue; + } + $description = isset($split[2]) ? $split[2] : null; + $type = $split[0]; + + $this->checkParam($phpcsFile, current($param), $stackPtr, $tag, $name, $type, $description); + } + + $last = current($this->processedParams); + foreach ($this->processedParams as $current) { + if ($last > $current) { + $error = 'Wrong param order, the first wrong is %s'; + $data = [ + $paramsMap[$current]['name'], + ]; + $fix = $phpcsFile->addFixableError($error, $paramsMap[$current]['token'], 'WrongParamOrder', $data); + + if ($fix) { + $this->fixParamOrder($phpcsFile, $paramsMap, $current); + } + + break; + } + + $last = $current; + } + } + + /** + * @param string[] $map + * @param int $wrong + */ + private function fixParamOrder(File $phpcsFile, array $map, $wrong) + { + $tokens = $phpcsFile->getTokens(); + + $tagPtr = $map[$wrong]['token']; + + $line = $tokens[$tagPtr]['line']; + // Find first element in line with token, all it will be moved. + $start = $phpcsFile->findFirstOnLine([], $tagPtr, true); + + $end = $tagPtr; + while (true) { + while ($tokens[$end + 1]['line'] === $line) { + ++$end; + } + + $next = $phpcsFile->findNext( + [T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR], + $end, + null, + true + ); + + if ($tokens[$next]['code'] !== T_DOC_COMMENT_STRING + || $tokens[$next]['line'] !== $line + 1 + ) { + break; + } + + ++$line; + $end = $next; + } + + $contentToMove = $phpcsFile->getTokensAsString($start, $end - $start + 1); + + // Where to move? + foreach ($map as $key => $data) { + if ($key > $wrong) { + $moveBefore = $phpcsFile->findFirstOnLine([], $data['token'], true); + break; + } + } + + $phpcsFile->fixer->beginChangeset(); + // Remove param from the old position. + for ($i = $start; $i <= $end; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + // Put param in the new position. + $phpcsFile->fixer->addContentBefore($moveBefore, $contentToMove); + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param int $varPtr + * @param string $newTypeHint + */ + private function replaceParamTypeHint(File $phpcsFile, $varPtr, $newTypeHint) + { + $last = $phpcsFile->findPrevious(T_STRING, $varPtr - 1); + $first = $phpcsFile->findPrevious([T_NULLABLE, T_STRING, T_NS_SEPARATOR], $last, null, true); + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($last, $newTypeHint); + for ($i = $last - 1; $i > $first; --$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param string[] $param Real param function details. + * @param null|int $methodPtr Position of the method definition token. + * @param null|int $tagPtr Position of the @param tag. + * @param null|string $name Name of the param in the @param tag. + * @param null|string $typeStr Type of the param in the @param tag. + * @param null|string $description Description of the param in the @param tag. + */ + private function checkParam( + File $phpcsFile, + array $param, + $methodPtr = null, + $tagPtr = null, + $name = null, + $typeStr = null, + $description = null + ) { + $typeHint = $param['type_hint']; + + if ($typeHint) { + $suggestedType = $this->getSuggestedType($typeHint); + + if ($suggestedType !== $typeHint) { + $error = 'Invalid type hint for param %s; expected "%s", but found "%s"'; + $data = [ + $param['name'], + $suggestedType, + $typeHint, + ]; + $fix = $phpcsFile->addFixableError($error, $param['token'], 'InvalidTypeHint', $data); + + if ($fix) { + $this->replaceParamTypeHint( + $phpcsFile, + $param['token'], + $suggestedType + ); + } + + $typeHint = $suggestedType; + } + } + $lowerTypeHint = strtolower($typeHint); + + // There is no param tag for the parameter + if (! $tagPtr) { + if (! $typeHint) { + $error = 'Parameter %s needs specification in PHPDocs'; + $data = [ + $param['name'], + ]; + $phpcsFile->addError($error, $param['token'], 'MissingSpecification', $data); + } elseif (in_array($lowerTypeHint, $this->needSpecificationTypes, true)) { + $type = strtr($lowerTypeHint, ['\\' => '', '?' => '']); + $code = sprintf('ParamType%sSpecification', ucfirst($type)); + $error = 'Parameter "%s" needs better specification in PHPDocs'; + $data = [ + $param['name'], + ]; + $phpcsFile->addError($error, $param['token'], $code, $data); + } elseif (isset($param['default']) + && strtolower($param['default']) === 'null' + && $typeHint[0] !== '?' + ) { + $error = 'Parameter %s needs specification in PHPDocs'; + $data = [ + $param['name'], + ]; + $fix = $phpcsFile->addFixableError($error, $param['token'], 'MissingSpecificationNUll', $data); + + if ($fix) { + $this->addParameter($phpcsFile, $methodPtr, $param['name'], 'null|' . $param['type_hint']); + } + } + + return; + } + + $clearName = str_replace('.', '', $name); + $isVariadic = $name !== $clearName; + + if ($param['name'] !== $clearName) { + $error = 'Parameter name is not consistent, found: "%s" and "%s"'; + $data = [ + $clearName, + $param['name'], + ]; + $phpcsFile->addError($error, $tagPtr, 'InconsistentParamName', $data); + } + + $isSpecVariadic = $param['variable_length'] === true; + if ($isVariadic xor $isSpecVariadic) { + $error = 'Parameter variadic inconsistent'; + $phpcsFile->addError($error, $tagPtr, 'InconsistentVariadic'); + } + + $types = explode('|', $typeStr); + + // Check if types are unique. + $uniq = array_unique($types); + if ($uniq !== $types) { + $expected = implode('|', $uniq); + $error = 'Duplicated types in param tag; expected "%s", but found "%s"'; + $data = [ + $expected, + implode('|', $types), + ]; + $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'DuplicateParamDocTypes', $data); + + if ($fix) { + $content = trim($expected . ' ' . $name . ' ' . $description); + $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); + } + + return; + } + + // Check if null is one of the types + if (($param['nullable_type'] + || (isset($param['default']) && strtolower($param['default']) === 'null')) + && ! preg_grep('/^null$/i', $types) + ) { + $error = 'Missing type "null" for nullable parameter %s'; + $data = [ + $param['name'], + ]; + $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'ParamDocMissingNull', $data); + + if ($fix) { + $content = trim('null|' . implode('|', $types) . ' ' . $name . ' ' . $description); + $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); + } + } + + $break = false; + foreach ($types as $key => $type) { + $lower = strtolower($type); + + if ($lower === 'null' + && $typeHint + && ! $param['nullable_type'] + && (! isset($param['default']) + || $param['default'] !== 'null') + ) { + $error = 'Param %s cannot have "null" value'; + $data = [ + $name, + ]; + $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'ParamDocNull', $data); + + if ($fix) { + unset($types[$key]); + $content = trim(implode('|', $types) . ' ' . $name . ' ' . $description); + $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); + } + + $break = true; + continue; + } + + if (stripos($type, 'null[') === 0) { + $error = 'Param type "%s" is not a valid type'; + $data = [ + $type, + ]; + $phpcsFile->addError($error, $tagPtr + 2, 'ParamDocNullArray', $data); + + $break = true; + continue; + } + + if ($lower === 'mixed' + || stripos($type, 'mixed[') === 0 + ) { + $error = 'Param type "mixed" is not allowed. Please specify the type.'; + $phpcsFile->addError($error, $tagPtr + 2, 'ParamDocMixed'); + + $break = true; + continue; + } + + $clearType = strtr($lower, ['[' => '', ']' => '']); + if (in_array($clearType, ['void', 'true', 'false'], true)) { + $error = 'Invalid param type: "%s"'; + $code = sprintf('InvalidParam%sType', ucfirst($clearType)); + $data = [ + $type, + ]; + $phpcsFile->addError($error, $tagPtr + 2, $code, $data); + + $break = true; + continue; + } + + if (array_filter($this->needSpecificationTypes, function ($v) use ($lower) { + return $lower === $v || strpos($lower, $v . '[') === 0; + })) { + $type = str_replace('\\', '', $lower); + $code = sprintf('Param%sSpecification', ucfirst($type)); + $data = [ + stripos($type, 'traversable') !== false ? ucfirst($type) : $type, + ]; + $error = 'Param type "%s" needs better specification'; + $phpcsFile->addError($error, $tagPtr + 2, $code, $data); + + $break = true; + continue; + } + + $suggestedType = $this->getSuggestedType($type); + if ($suggestedType !== $type) { + $error = 'Invalid param type; expected "%s", but found "%s"'; + $data = [ + $suggestedType, + $type, + ]; + $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'InvalidParamDocType', $data); + + if ($fix) { + $types[$key] = $suggestedType; + $content = trim(implode('|', $types) . ' ' . $name . ' ' . $description); + $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); + } + + $break = true; + continue; + } + + if ($typeHint) { + // array + if (in_array($lowerTypeHint, ['array', '?array'], true) + && ! in_array($lower, ['null', 'array'], true) + && strpos($type, '[]') === false + ) { + $error = 'Param type contains "%s" which is not an array type'; + $data = [ + $type, + ]; + $phpcsFile->addError($error, $tagPtr + 2, 'NotArrayType', $data); + + $break = true; + continue; + } + + // iterable + if (in_array($lowerTypeHint, ['iterable', '?iterable'], true) + && in_array($lower, $this->simpleReturnTypes, true) + ) { + $error = 'Param type contains "%s" which is not an iterable type'; + $data = [ + $type, + ]; + $phpcsFile->addError($error, $tagPtr + 2, 'NotIterableType', $data); + + $break = true; + continue; + } + + // traversable + if (in_array($lowerTypeHint, [ + 'traversable', + '?traversable', + '\traversable', + '?\traversable', + ], true) + && ! in_array($lower, ['null', 'traversable', '\traversable'], true) + && (strpos($type, '[]') !== false + || in_array($lower, $this->simpleReturnTypes, true)) + ) { + $error = 'Param type contains "%s" which is not a traversable type'; + $data = [ + $type, + ]; + $phpcsFile->addError($error, $tagPtr + 2, 'NotTraversableType', $data); + + $break = true; + continue; + } + + if (! in_array($lowerTypeHint, $this->needSpecificationTypes, true) + && ((in_array($lowerTypeHint, $this->simpleReturnTypes, true) + && $lower !== 'null' + && $lower !== $lowerTypeHint + && '?' . $lower !== $lowerTypeHint) + || (! in_array($lowerTypeHint, $this->simpleReturnTypes, true) + && array_filter($this->simpleReturnTypes, function ($v) use ($lower) { + return $v === $lower || strpos($lower, $v . '[') === 0; + }))) + ) { + $error = 'Invalid type "%s" for parameter %s'; + $data = [ + $type, + $name, + ]; + $phpcsFile->addError($error, $tagPtr, 'ParamDocInvalidType', $data); + + $break = true; + continue; + } + } + } + + // If some parameter is invalid, we don't want to preform other checks + if ($break) { + return; + } + + // Check if order of return types is as expected: first null, then simple types, and then complex. + $unsorted = implode('|', $types); + usort($types, function ($a, $b) { + return $this->sortTypes($a, $b); + }); + $content = implode('|', $types); + if ($content !== $unsorted) { + $error = 'Invalid order of param types in @param tag; expected "%s" but found "%s"'; + $data = [ + $content, + $unsorted, + ]; + $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'ReturnTypesOrder', $data); + + if ($fix) { + $content = trim($content . ' ' . $name . ' ' . $description); + $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); + } + } + + // Check if PHPDocs param is required + if ($typeHint + && ! in_array($lowerTypeHint, $this->needSpecificationTypes, true) + && $this->typesMatch($typeHint, $typeStr) + && ! $description + ) { + $error = 'Param tag is redundant'; + $fix = $phpcsFile->addFixableError($error, $tagPtr, 'RedundantParamDoc'); + + if ($fix) { + $this->removeTag($phpcsFile, $tagPtr); + } + } + } + + /** + * @param string $str + * @return bool + */ + private function isVariable($str) + { + return strpos($str, '$') === 0 + || strpos($str, '...$') === 0; + } + + /** + * @param string $str + * @return bool + */ + private function isType($str) + { + return (bool) preg_match('/^((?:\\\\?[a-z0-9]+)+(?:\[\])*)(\|(?:\\\\?[a-z0-9]+)+(?:\[\])*)*$/i', $str); + } + + /** + * @param int $stackPtr + */ + private function processParamSpec(File $phpcsFile, $stackPtr) + { + foreach ($this->params as $k => $param) { + if (in_array($k, $this->processedParams, true)) { + continue; + } + + $this->checkParam($phpcsFile, $param, $stackPtr); + } + } + + /** + * @param int $methodPtr + * @param string $name + * @param string $type + */ + private function addParameter(File $phpcsFile, $methodPtr, $name, $type) + { + $tokens = $phpcsFile->getTokens(); + + $skip = Tokens::$methodPrefixes + + [T_WHITESPACE => T_WHITESPACE]; + + $commentEnd = $phpcsFile->findPrevious($skip, $methodPtr - 1, null, true); + if ($tokens[$commentEnd]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + $firstOnLine = $phpcsFile->findFirstOnLine([], $commentEnd, true); + $indent = ' '; + $content = '* @param %3$s %4$s%2$s%1$s'; + if ($tokens[$firstOnLine]['code'] === T_DOC_COMMENT_WHITESPACE) { + $indent = $tokens[$firstOnLine]['content']; + } elseif ($tokens[$firstOnLine]['code'] === T_WHITESPACE) { + $indent .= $tokens[$firstOnLine]['content']; + $content = '%2$s%1$s* @param %3$s %4$s%2$s%1$s'; + } + + $before = $commentEnd; + } else { + $next = $phpcsFile->findNext(T_WHITESPACE, $commentEnd + 1, null, true); + $firstOnLine = $phpcsFile->findFirstOnLine([], $next, true); + $indent = ''; + if ($tokens[$firstOnLine]['code'] === T_WHITESPACE) { + $indent = $tokens[$firstOnLine]['content']; + } + + $content = '%1$s/**%2$s' + . '%1$s * @param %3$s %4$s%2$s' + . '%1$s */%2$s'; + + $before = $firstOnLine; + } + + $content = sprintf( + $content, + $indent, + $phpcsFile->eolChar, + $type, + $name + ); + + $phpcsFile->fixer->addContentBefore($before, $content); + } +} diff --git a/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php new file mode 100644 index 00000000..10c60967 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php @@ -0,0 +1,1057 @@ +initScope($phpcsFile, $stackPtr); + + $this->returnDoc = null; + $this->returnDocTypes = []; + $this->returnDocValue = null; + $this->returnDocDescription = null; + $this->returnDocIsValid = true; + + $this->returnType = null; + $this->returnTypeValue = null; + $this->returnTypeIsValid = true; + + if ($commentStart = $this->getCommentStart($phpcsFile, $stackPtr)) { + $this->processReturnDoc($phpcsFile, $commentStart); + } + $this->processReturnType($phpcsFile, $stackPtr); + $this->processReturnStatements($phpcsFile, $stackPtr); + } + + /** + * @param int $stackPtr + * @return bool|int + */ + private function getReturnType(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener'])) { + $to = $tokens[$stackPtr]['scope_opener']; + } else { + $to = $phpcsFile->findEndOfStatement($stackPtr, [T_COLON]); + } + + return $phpcsFile->findNext(T_RETURN_TYPE, $stackPtr + 1, $to); + } + + /** + * @param int $commentStart + */ + private function processReturnDoc(File $phpcsFile, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + $returnDoc = null; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if (strtolower($tokens[$tag]['content']) !== '@return') { + continue; + } + + if ($returnDoc !== null) { + $error = 'Only 1 @return tag is allowed in a function comment'; + $phpcsFile->addError($error, $tag, 'DuplicateReturn'); + + $this->returnDoc = $returnDoc; + $this->returnDocIsValid = false; + return; + } + + if ($this->isSpecialMethod) { + $error = sprintf('@return tag is not allowed for "%s" method', $this->methodName); + $phpcsFile->addError($error, $tag, 'SpecialMethodReturnTag'); + } + + if ($tokens[$tag + 2]['code'] !== T_DOC_COMMENT_STRING) { + $error = 'Return type missing for @return tag in function comment'; + $phpcsFile->addError($error, $tag, 'MissingReturnTypeDoc'); + + $this->returnDoc = $tag; + $this->returnDocIsValid = false; + return; + } + + $returnDoc = $tag; + } + + if (! $returnDoc || $this->isSpecialMethod) { + return; + } + + $this->returnDoc = $returnDoc; + + $split = preg_split('/\s/', $tokens[$returnDoc + 2]['content'], 2); + $this->returnDocValue = $split[0]; + $this->returnDocDescription = isset($split[1]) ? trim($split[1]) : null; + + if (strtolower($this->returnDocValue) === 'void') { + if ($this->returnDocDescription) { + $error = 'Description for return "void" type is not allowed.' + . 'Please move it to method description.'; + $phpcsFile->addError($error, $returnDoc, 'ReturnVoidDescription'); + + $this->returnDocIsValid = false; + return; + } + + $error = 'Return tag "void" is redundant.'; + $fix = $phpcsFile->addFixableError($error, $returnDoc, 'ReturnVoid'); + + if ($fix) { + $this->removeTag($phpcsFile, $returnDoc); + } + + $this->returnDocIsValid = false; + return; + } + + $isThis = in_array(strtolower($this->returnDocValue), ['$this', '$this|null', 'null|$this'], true); + if (! $isThis + && ! preg_match( + '/^((?:\\\\?[a-z0-9]+)+(?:\[\])*)(\|(?:\\\\?[a-z0-9]+)+(?:\[\])*)*$/i', + $this->returnDocValue + ) + ) { + $error = 'Return type has invalid format'; + $phpcsFile->addError($error, $returnDoc + 2, 'ReturnInvalidFormat'); + + $this->returnDocIsValid = false; + return; + } + + if ($isThis + && strtolower($this->returnDocValue) !== $this->returnDocValue + ) { + $error = 'Invalid case of return type; expected %s but found %s'; + $data = [ + '$this', + $this->returnDocValue, + ]; + $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'InvalidReturnThis', $data); + + if ($fix) { + $content = trim(strtolower($this->returnDocValue) . ' ' . $this->returnDocDescription); + $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); + } + } + + // Return tag contains only null, null[], null[][], ... + $cleared = strtolower(strtr($this->returnDocValue, ['[' => '', ']' => ''])); + if ($cleared === 'null') { + $error = 'Return tag contains only "null". Please specify all returned types'; + $data = [ + $this->returnDocValue, + ]; + $code = sprintf('ReturnOnly%s', ucfirst($cleared)); + $phpcsFile->addError($error, $returnDoc + 2, $code, $data); + + $this->returnDocIsValid = false; + return; + } + + $hasInvalidType = false; + $this->returnDocTypes = explode('|', $this->returnDocValue); + foreach ($this->returnDocTypes as $key => $type) { + $lower = strtolower($type); + + if ($lower === 'mixed' + || strpos($lower, 'mixed[') === 0 + ) { + $error = 'Return type "mixed" type is not allowed. Please specify the type.'; + $phpcsFile->addError($error, $returnDoc + 2, 'ReturnMixed'); + + $hasInvalidType = true; + continue; + } + + if ($lower === 'void') { + // If void is mixed up with other return types. + $error = 'Return "void" is mixed with other types. Please use null instead.'; + $phpcsFile->addError($error, $returnDoc + 2, 'ReturnVoidWithOther'); + + $hasInvalidType = true; + continue; + } + + if (array_filter($this->needSpecificationTypes, function ($v) use ($type) { + return strtolower($type) === $v || stripos($type, $v . '[') === 0; + })) { + $type = str_replace('\\', '', strtolower($type)); + $code = sprintf('Return%sSpecification', ucfirst($type)); + $data = [ + stripos($type, 'traversable') !== false ? ucfirst($type) : $type, + ]; + $error = 'Return type "%s" needs better specification'; + $phpcsFile->addError($error, $returnDoc + 2, $code, $data); + + $hasInvalidType = true; + continue; + } + + if (in_array(strtolower($type), ['null', 'true', 'false'], true)) { + $suggestedType = strtolower($type); + } else { + $suggestedType = $this->getSuggestedType($type); + } + if ($suggestedType !== $type) { + if (strpos($suggestedType, 'self') === 0) { + $error = 'Return type cannot be class name. Please use "self", "static" or "$this" instead' + . ' depends what you expect to be returned'; + $phpcsFile->addError($error, $returnDoc + 2, 'InvalidReturnClassName'); + + $hasInvalidType = true; + continue; + } + + $error = 'Invalid return type; expected "%s", but found "%s"'; + $data = [ + $suggestedType, + $type, + ]; + $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'InvalidReturn', $data); + + if ($fix) { + $this->returnDocTypes[$key] = $suggestedType; + $content = trim(implode('|', $this->returnDocTypes) . ' ' . $this->returnDocDescription); + $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); + } + + $hasInvalidType = true; + continue; + } + } + + if ($hasInvalidType) { + return; + } + + // Check boolean values in return tag + $lowerReturnDocTypes = explode('|', strtolower($this->returnDocValue)); + $hasTrue = in_array('true', $lowerReturnDocTypes, true); + $hasFalse = in_array('false', $lowerReturnDocTypes, true); + if (in_array('bool', $lowerReturnDocTypes, true)) { + if ($hasTrue) { + $error = 'Return tag contains "bool" and "true". Please use just "bool"'; + $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'ReturnBoolAndTrue'); + + if ($fix) { + $types = array_filter($this->returnDocTypes, function ($v) { + return strtolower($v) !== 'true'; + }); + $content = trim(implode('|', $types) . ' ' . $this->returnDocDescription); + $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); + } + + return; + } + + if ($hasFalse) { + $error = 'Return tag contains "bool" and "false". Please use just "bool"'; + $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'ReturnBoolAndFalse'); + + if ($fix) { + $types = array_filter($this->returnDocTypes, function ($v) { + return strtolower($v) !== 'false'; + }); + $content = trim(implode('|', $types) . ' ' . $this->returnDocDescription); + $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); + } + + return; + } + } elseif ($hasTrue && $hasFalse) { + $error = 'Return tag contains "true" and "false". Please use "bool" instead.'; + $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'ReturnTrueAndFalse'); + + if ($fix) { + $types = array_filter($this->returnDocTypes, function ($v) { + return ! in_array(strtolower($v), ['true', 'false'], true); + }); + $types[] = 'bool'; + $content = trim(implode('|', $types) . ' ' . $this->returnDocDescription); + $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); + } + + return; + } + + // Check if types are unique. + $uniq = array_unique($this->returnDocTypes); + if ($uniq !== $this->returnDocTypes) { + $expected = implode('|', $uniq); + $error = 'Duplicated types in return tag; expected "%s", but found "%s"'; + $data = [ + $expected, + $this->returnDocValue, + ]; + $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'DuplicateReturnDocTypes', $data); + + if ($fix) { + $content = trim($expected . ' ' . $this->returnDocDescription); + $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); + } + + return; + } + + // Check if order of return types is as expected: first null, then simple types, and then complex. + usort($this->returnDocTypes, function ($a, $b) { + return $this->sortTypes($a, $b); + }); + $content = implode('|', $this->returnDocTypes); + if ($content !== $this->returnDocValue) { + $error = 'Invalid order of return types in @return tag; expected "%s" but found "%s"'; + $data = [ + $content, + $this->returnDocValue, + ]; + $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'ReturnTypesOrder', $data); + + if ($fix) { + $content = trim($content . ' ' . $this->returnDocDescription); + $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); + } + } + } + + /** + * @param int $stackPtr + */ + private function processReturnType(File $phpcsFile, $stackPtr) + { + // Get return type from method signature + $returnType = $this->getReturnType($phpcsFile, $stackPtr); + if (! $returnType) { + return; + } + + $this->returnType = $returnType; + + if ($this->isSpecialMethod) { + $error = 'Method "%s" cannot declare return type'; + $data = [$this->methodName]; + $phpcsFile->addError($error, $stackPtr, 'SpecialMethodReturnType', $data); + + $this->returnTypeIsValid = false; + return; + } + + $colon = $phpcsFile->findPrevious(T_COLON, $returnType - 1, $stackPtr + 1); + $firstNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $colon + 1, null, true); + + $this->returnTypeValue = preg_replace( + '/\s/', + '', + $phpcsFile->getTokensAsString($firstNonEmpty, $returnType - $firstNonEmpty + 1) + ); + $lowerReturnTypeValue = strtolower($this->returnTypeValue); + + $suggestedType = $this->getSuggestedType($this->returnTypeValue); + if ($suggestedType !== $this->returnTypeValue) { + $error = 'Invalid return type; expected %s, but found %s'; + $data = [ + $suggestedType, + $this->returnTypeValue, + ]; + $fix = $phpcsFile->addFixableError($error, $returnType, 'InvalidReturnType', $data); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $firstNonEmpty; $i < $returnType; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->replaceToken($returnType, $suggestedType); + $phpcsFile->fixer->endChangeset(); + } + + return; + } + + if (! $this->returnDoc + && in_array($lowerReturnTypeValue, $this->needSpecificationTypes, true) + ) { + $type = strtr($lowerReturnTypeValue, ['\\' => '', '?' => '']); + $code = sprintf('ReturnType%sSpecification', ucfirst($type)); + $error = 'Return type "%s" needs better specification in PHPDocs.'; + $data = [ + $type === 'traversable' ? ucfirst($type) : $type, + ]; + $phpcsFile->addError($error, $returnType, $code, $data); + + return; + } + + if (! $this->returnDoc || ! $this->returnDocIsValid) { + return; + } + + $hasNullInDoc = preg_grep('/^null$/i', $this->returnDocTypes); + + if (! $hasNullInDoc && $this->returnTypeValue[0] === '?') { + $error = 'Missing "null" as possible return type in PHPDocs.' + . ' Nullable type has been found in return type declaration.'; + $fix = $phpcsFile->addFixableError($error, $this->returnDoc + 2, 'MissingNull'); + + if ($fix) { + $content = trim('null|' . $this->returnDocValue . ' ' . $this->returnDocDescription); + $phpcsFile->fixer->replaceToken($this->returnDoc + 2, $content); + } + + return; + } + + if ($hasNullInDoc && $this->returnTypeValue[0] !== '?') { + $error = 'Null type has been found in PHPDocs for return type.' + . ' It is not declared with function return type.'; + $fix = $phpcsFile->addFixableError($error, $this->returnDoc + 2, 'AdditionalNull'); + + if ($fix) { + foreach ($this->returnDocTypes as $key => $type) { + if (strtolower($type) === 'null') { + unset($this->returnDocTypes[$key]); + break; + } + } + + $content = trim(implode('|', $this->returnDocTypes) . ' ' . $this->returnDocDescription); + $phpcsFile->fixer->replaceToken($this->returnDoc + 2, $content); + } + + return; + } + + if (! in_array($lowerReturnTypeValue, $this->needSpecificationTypes, true)) { + if ($this->typesMatch($this->returnTypeValue, $this->returnDocValue)) { + // There is no description and values are the same so PHPDoc tag is redundant. + if (! $this->returnDocDescription) { + $error = 'Return tag is redundant'; + $fix = $phpcsFile->addFixableError($error, $this->returnDoc, 'RedundantReturnDoc'); + + if ($fix) { + $this->removeTag($phpcsFile, $this->returnDoc); + } + } + + return; + } + + if (in_array($lowerReturnTypeValue, ['parent', '?parent'], true)) { + if (! in_array(strtolower($this->returnDocValue), [ + 'parent', + 'null|parent', + 'parent|null', + 'self', + 'null|self', + 'self|null', + 'static', + 'null|static', + 'static|null', + '$this', + 'null|$this', + '$this|null', + ], true)) { + $error = 'Return type is "parent" so return tag must be one of:' + . ' "parent", "self", "static" or "$this"'; + $phpcsFile->addError($error, $this->returnDoc + 2, 'ReturnParent'); + } + + return; + } + + if (in_array($lowerReturnTypeValue, ['self', '?self'], true)) { + if (! in_array(strtolower($this->returnDocValue), [ + 'self', + 'null|self', + 'self|null', + 'static', + 'null|static', + 'static|null', + '$this', + 'null|$this', + '$this|null', + ], true)) { + $error = 'Return type is "self" so return tag must be one of: "self", "static" or "$this"'; + $phpcsFile->addError($error, $this->returnDoc + 2, 'ReturnSelf'); + } + + return; + } + + if (! in_array($lowerReturnTypeValue, $this->simpleReturnTypes, true)) { + foreach ($this->returnDocTypes as $type) { + $lower = strtolower($type); + if (array_filter($this->simpleReturnTypes, function ($v) use ($lower) { + return $v === $lower || strpos($lower, $v . '[') === 0; + })) { + $error = 'Unexpected type "%s" found in return tag'; + $data = [ + $type, + ]; + $phpcsFile->addError($error, $this->returnDoc + 2, 'ReturnComplexType', $data); + } + } + + return; + } + + $error = 'Return type in PHPDoc tag is different than declared type in method declaration: "%s" and "%s"'; + $data = [ + $this->returnDocValue, + $this->returnTypeValue, + ]; + $phpcsFile->addError($error, $this->returnDoc + 2, 'DifferentTagAndDeclaration', $data); + + return; + } + + switch ($lowerReturnTypeValue) { + case 'array': + case '?array': + foreach ($this->returnDocTypes as $type) { + if (in_array(strtolower($type), ['null', 'array'], true)) { + continue; + } + + if (strpos($type, '[]') === false) { + $error = 'Return type contains "%s" which is not an array type'; + $data = [ + $type, + ]; + $phpcsFile->addError($error, $this->returnDoc + 2, 'NotArrayType', $data); + } + } + break; + + case 'iterable': + case '?iterable': + foreach ($this->returnDocTypes as $type) { + $lower = strtolower($type); + if ($lower === 'iterable') { + continue; + } + + if (in_array($lower, $this->simpleReturnTypes, true)) { + $error = 'Return type contains "%s" which is not an iterable type'; + $data = [ + $type, + ]; + $phpcsFile->addError($error, $this->returnDoc + 2, 'NotIterableType', $data); + } + } + break; + + case 'traversable': + case '?traversable': + case '\traversable': + case '?\traversable': + foreach ($this->returnDocTypes as $type) { + $lower = strtolower($type); + if (in_array($lower, ['null', 'traversable', '\traversable'], true)) { + continue; + } + + if (strpos($type, '[]') !== false + || in_array($lower, $this->simpleReturnTypes, true) + ) { + $error = 'Return type contains "%s" which is not a traversable type'; + $data = [ + $type, + ]; + $phpcsFile->addError($error, $this->returnDoc + 2, 'NotTraversableType', $data); + } + } + break; + } + } + + /** + * @param int $stackPtr + */ + private function processReturnStatements(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Method does not have a body. + if (! isset($tokens[$stackPtr]['scope_opener'])) { + return; + } + + $returnValues = []; + + // Search all return/yield/yield from in the method. + for ($i = $tokens[$stackPtr]['scope_opener'] + 1; $i < $tokens[$stackPtr]['scope_closer']; ++$i) { + // Skip closures and anonymous classes. + if ($tokens[$i]['code'] === T_CLOSURE + || $tokens[$i]['code'] === T_ANON_CLASS + ) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + if ($tokens[$i]['code'] !== T_RETURN + && $tokens[$i]['code'] !== T_YIELD + && $tokens[$i]['code'] !== T_YIELD_FROM + ) { + continue; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $i + 1, null, true); + if ($tokens[$next]['code'] === T_SEMICOLON) { + $this->returnCodeVoid($phpcsFile, $i); + } else { + $this->returnCodeValue($phpcsFile, $i); + $returnValues[$next] = $this->getReturnValue($phpcsFile, $next); + + if ($this->returnDoc + && $this->returnDocIsValid + && in_array(strtolower($this->returnDocValue), ['$this', 'null|$this', '$this|null'], true) + ) { + $isThis = ! in_array($tokens[$next]['code'], [ + T_CLOSURE, + T_CONSTANT_ENCAPSED_STRING, + T_DIR, + T_DOUBLE_QUOTED_STRING, + T_FILE, + T_NEW, + T_NS_SEPARATOR, + T_OPEN_PARENTHESIS, + T_OBJECT_CAST, + T_SELF, + T_STATIC, + T_STRING_CAST, + T_PARENT, + ], true); + + if ($isThis + && $tokens[$next]['code'] === T_VARIABLE + && (strtolower($tokens[$next]['content']) !== '$this' + || (($next = $phpcsFile->findNext(Tokens::$emptyTokens, $next + 1, null, true)) + && $tokens[$next]['code'] !== T_SEMICOLON)) + ) { + $isThis = false; + } + + if (! $isThis) { + $error = 'Return type of "%s" function is "$this",' + . ' but function is returning not $this here'; + $data = [$this->methodName]; + $phpcsFile->addError($error, $i, 'InvalidReturnNotThis', $data); + } + } + } + } + + if (! $returnValues + && (($this->returnDoc && $this->returnDocIsValid) + || ($this->returnType && $this->returnTypeIsValid && strtolower($this->returnTypeValue) !== 'void')) + ) { + $error = 'Return type of "%s" function is not void, but function has no return statement'; + $data = [$this->methodName]; + $phpcsFile->addError( + $error, + $this->returnDoc && $this->returnDocIsValid ? $this->returnDoc : $this->returnType, + 'InvalidNoReturn', + $data + ); + } + + if (! $returnValues || ! $this->returnDoc || ! $this->returnDocIsValid) { + return; + } + + $uniq = array_unique($returnValues); + if (count($uniq) === 1) { + // We have to use current because index in the array is $ptr + switch (current($uniq)) { + case 'array': + if ($matches = array_udiff( + preg_grep('/[^\]]$/', $this->returnDocTypes), + ['null', 'array', 'iterable'], + function ($a, $b) { + return strcasecmp($a, $b); + } + )) { + $error = 'Function returns only array, but return type contains not array types: %s'; + $data = [ + implode(', ', $matches), + ]; + $phpcsFile->addError($error, $this->returnDoc, 'ReturnArrayOnly', $data); + } + break; + + case 'bool': + if (! in_array(strtolower($this->returnDocValue), ['bool', 'boolean'], true)) { + $error = 'Functions returns only boolean value, but return type is not only bool'; + $phpcsFile->addError($error, $this->returnDoc, 'ReturnBoolOnly'); + } + break; + + case 'false': + if (strtolower($this->returnDocValue) !== 'false') { + $error = 'Function returns only boolean false, but return type is not only false'; + $phpcsFile->addError($error, $this->returnDoc, 'ReturnFalseOnly'); + } + break; + + case 'true': + if (strtolower($this->returnDocValue) !== 'true') { + $error = 'Function returns only boolean true, but return type is not only true'; + $phpcsFile->addError($error, $this->returnDoc, 'ReturnTrueOnly'); + } + break; + + case 'new': + $instances = []; + foreach ($returnValues as $ptr => $new) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $ptr + 1, null, true); + if ($tokens[$next]['code'] !== T_STRING + && $tokens[$next]['code'] !== T_NS_SEPARATOR + ) { + // It is unknown instance, break switch. + break 2; + } + + $after = $phpcsFile->findNext( + Tokens::$emptyTokens + + [T_NS_SEPARATOR => T_NS_SEPARATOR, T_STRING => T_STRING], + $next + 1, + null, + true + ); + + $last = $phpcsFile->findPrevious(T_STRING, $after - 1, $next); + $content = $this->getSuggestedType( + $phpcsFile->getTokensAsString($next, $last - $next + 1) + ); + + $instances[strtolower($content)] = $content; + } + + // If function returns instances of different types, break. + if (count($instances) !== 1) { + break; + } + + $className = current($instances); + if ($this->returnDocValue !== $className) { + $error = 'Function returns only new instance of %s, but return type is not only %s'; + $data = [ + $className, + $className, + ]; + $phpcsFile->addError($error, $this->returnDoc + 2, 'ReturnNewInstanceOnly', $data); + } + break; + + case '$this': + if (($isClassName = $this->isClassName($this->returnDocValue)) + || strtolower($this->returnDocValue) === 'self' + ) { + $error = 'Function returns only $this so return type should be $this instead of ' + . ($isClassName ? 'class name' : 'self'); + $fix = $phpcsFile->addFixableError($error, $this->returnDoc + 2, 'ReturnThisOnly'); + + if ($fix) { + $content = trim('$this ' . $this->returnDocDescription); + $phpcsFile->fixer->replaceToken($this->returnDoc + 2, $content); + } + } + break; + } + } + } + + /** + * @param int $ptr + * @return string + */ + private function getReturnValue(File $phpcsFile, $ptr) + { + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$ptr]['code']) { + case T_ARRAY: + case T_ARRAY_CAST: + case T_OPEN_SHORT_ARRAY: + if (! $this->hasCorrectType(['array', '?array', 'iterable', '?iterable'], []) + || ($this->returnDoc + && $this->returnDocIsValid + && strpos($this->returnDocValue, '[]') === false + && ! array_intersect( + explode('|', strtolower($this->returnDocValue)), + ['array', 'iterable'] + )) + ) { + $error = 'Function return type is array nor iterable, but function returns array here'; + $phpcsFile->addError($error, $ptr, 'ReturnArray'); + } + return 'array'; + + case T_BOOL_CAST: + case T_BOOLEAN_NOT: + $end = $ptr; + while (++$end) { + if ($tokens[$end]['code'] === T_OPEN_PARENTHESIS) { + $end = $tokens[$end]['parenthesis_closer']; + continue; + } + if ($tokens[$end]['code'] === T_OPEN_SQUARE_BRACKET + || $tokens[$end]['code'] === T_OPEN_CURLY_BRACKET + || $tokens[$end]['code'] === T_OPEN_SHORT_ARRAY + ) { + $end = $tokens[$end]['bracket_closer']; + continue; + } + + if (in_array($tokens[$end]['code'], [T_SEMICOLON, T_INLINE_THEN], true)) { + break; + } + } + if ($tokens[$end]['code'] !== T_SEMICOLON) { + return 'unknown'; + } + + if (! $this->hasCorrectType(['bool', '?bool'], ['bool', 'boolean'])) { + $error = 'Function return type is not bool, but function returns boolean value here'; + $phpcsFile->addError($error, $ptr, 'ReturnFloat'); + } + return 'bool'; + + case T_FALSE: + if (! $this->hasCorrectType(['bool', '?bool'], ['bool', 'boolean', 'false'])) { + $error = 'Function return type is not bool, but function returns boolean false here'; + $phpcsFile->addError($error, $ptr, 'ReturnFalse'); + } + return 'false'; + + case T_TRUE: + if (! $this->hasCorrectType(['bool', '?bool'], ['bool', 'boolean', 'true'])) { + $error = 'Function return type is not bool, but function returns boolean true here'; + $phpcsFile->addError($error, $ptr, 'ReturnTrue'); + } + return 'true'; + + // integer value or integer cast + case T_LNUMBER: + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $ptr + 1, null, true); + if ($tokens[$next]['code'] !== T_SEMICOLON) { + return 'unknown'; + } + // no break + case T_INT_CAST: + if (! $this->hasCorrectType(['int', '?int'], ['int', 'integer'])) { + $error = 'Function return type is not int, but function return int here'; + $phpcsFile->addError($error, $ptr, 'ReturnInt'); + } + return 'int'; + + // float value or float cast + case T_DNUMBER: + case T_DOUBLE_CAST: + if (! $this->hasCorrectType(['float', '?float'], ['double', 'float', 'real'])) { + $error = 'Function return type is not float, but function returns float here'; + $phpcsFile->addError($error, $ptr, 'ReturnFloat'); + } + return 'float'; + + case T_NEW: + return 'new'; + + case T_NULL: + if (! $this->hasCorrectType([], ['null']) + || ($this->returnType + && $this->returnTypeIsValid + && strpos($this->returnTypeValue, '?') !== 0) + ) { + $error = 'Function return type is not nullable, but function returns null here'; + $phpcsFile->addError($error, $ptr, 'ReturnNull'); + } + return 'null'; + + case T_VARIABLE: + if (strtolower($tokens[$ptr]['content']) !== '$this') { + return 'variable'; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $ptr + 1, null, true); + if ($tokens[$next]['code'] !== T_SEMICOLON) { + // This is not "$this" return but something else. + return 'unknown'; + } + return '$this'; + } + + return 'unknown'; + } + + /** + * @param string[] $expectedType + * @param string[] $expectedDoc + * @return bool + */ + private function hasCorrectType(array $expectedType, array $expectedDoc) + { + if ($expectedType + && $this->returnType + && $this->returnTypeIsValid + && ! in_array(strtolower($this->returnTypeValue), $expectedType, true) + ) { + return false; + } + + if ($expectedDoc + && $this->returnDoc + && $this->returnDocIsValid + && ! array_filter($this->returnDocTypes, function ($v) use ($expectedDoc) { + return in_array(strtolower($v), $expectedDoc, true); + }) + ) { + return false; + } + + return true; + } + + /** + * @param int $ptr + */ + private function returnCodeVoid(File $phpcsFile, $ptr) + { + if (($this->returnDoc && $this->returnDocIsValid) + || ($this->returnType && $this->returnTypeIsValid && strtolower($this->returnTypeValue) !== 'void') + ) { + $error = 'Return type of "%s" function is not void, but function is returning void here'; + $data = [$this->methodName]; + $phpcsFile->addError($error, $ptr, 'InvalidReturnNotVoid', $data); + } + } + + /** + * @param int $ptr + */ + private function returnCodeValue(File $phpcsFile, $ptr) + { + // Special method cannot return any values. + if ($this->isSpecialMethod) { + $error = 'Method "%s" cannot return any value, but returns it here'; + $data = [$this->methodName]; + $phpcsFile->addError($error, $ptr, 'SpecialMethodReturnValue', $data); + + return; + } + + // Function is void but return a value. + if ((! $this->returnType + || ! $this->returnTypeIsValid + || $this->returnTypeValue === 'void') + && (! $this->returnDoc + || ! $this->returnDocIsValid + || $this->returnDocValue === 'void') + ) { + $error = 'Function "%s" returns value but it is not specified.' + . ' Please add return tag or declare return type.'; + $data = [ + $this->methodName, + ]; + $phpcsFile->addError($error, $ptr, 'ReturnValue', $data); + } + } +} diff --git a/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php new file mode 100644 index 00000000..72a67326 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php @@ -0,0 +1,327 @@ +initScope($phpcsFile, $stackPtr); + + $this->throwTags = []; + + if ($commentStart = $this->getCommentStart($phpcsFile, $stackPtr)) { + $this->processThrowsDoc($phpcsFile, $commentStart); + } + $this->processThrowStatements($phpcsFile, $stackPtr); + } + + /** + * @param int $commentStart + */ + private function processThrowsDoc(File $phpcsFile, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if (strtolower($tokens[$tag]['content']) !== '@throws') { + continue; + } + + $exception = null; + if ($tokens[$tag + 2]['code'] === T_DOC_COMMENT_STRING) { + $split = preg_split('/\s/', $tokens[$tag + 2]['content'], 2); + $exception = $split[0]; + $description = isset($split[1]) ? trim($split[1]) : null; + $suggested = $this->getSuggestedType($exception); + + if ($exception !== $suggested) { + $error = 'Invalid exception type; expected %s, but found %s'; + $data = [ + $suggested, + $exception, + ]; + $fix = $phpcsFile->addFixableError($error, $tag + 2, 'InvalidType', $data); + + if ($fix) { + $content = trim($suggested . ' ' . $description); + $phpcsFile->fixer->replaceToken($tag + 2, $content); + } + } + + $this->throwTags[$tag] = $suggested; + } + + if (! $exception) { + $error = 'Exception type missing for @throws tag in function comment'; + $phpcsFile->addError($error, $tag, 'MissingType'); + } + } + } + + /** + * @param int $stackPtr + */ + protected function processThrowStatements(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Skip function without body + if (! isset($tokens[$stackPtr]['scope_opener'])) { + return; + } + + $scopeBegin = $tokens[$stackPtr]['scope_opener']; + $scopeEnd = $tokens[$stackPtr]['scope_closer']; + + $thrownExceptions = []; + $thrownVariables = 0; + $foundThrows = false; + + $throw = $scopeBegin; + while (true) { + $throw = $phpcsFile->findNext(T_THROW, $throw + 1, $scopeEnd); + + // Throw statement not found. + if (! $throw) { + break; + } + + // The throw statement is in another scope. + if (! $this->isLastScope($tokens[$throw]['conditions'], $stackPtr)) { + continue; + } + + $foundThrows = true; + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $throw + 1, null, true); + if ($tokens[$next]['code'] === T_NEW) { + $currException = $phpcsFile->findNext(Tokens::$emptyTokens, $next + 1, null, true); + + if (in_array($tokens[$currException]['code'], $this->nameTokens, true)) { + $end = $phpcsFile->findNext($this->nameTokens, $currException + 1, null, true); + + $class = $phpcsFile->getTokensAsString($currException, $end - $currException); + $suggested = $this->getSuggestedType($class); + + if ($class !== $suggested) { + $error = 'Invalid exception class name; expected %s, but found %s'; + $data = [ + $suggested, + $class, + ]; + $fix = $phpcsFile->addFixableError($error, $currException, 'InvalidExceptionClassName', $data); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($currException, $suggested); + for ($i = $currException + 1; $i < $end; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->endChangeset(); + } + } + + $thrownExceptions[] = $suggested; + } else { + // the next token is not a valid name - it could be variable name + $error = 'Expected exception class name'; + $phpcsFile->addError($error, $currException, 'ThrowClassName'); + } + } elseif ($tokens[$next]['code'] === T_VARIABLE) { + $catch = $phpcsFile->findPrevious(T_CATCH, $throw, $scopeBegin); + + if ($catch) { + $thrownVar = $phpcsFile->findPrevious( + T_VARIABLE, + $tokens[$catch]['parenthesis_closer'] - 1, + $tokens[$catch]['parenthesis_opener'] + ); + + if ($tokens[$thrownVar]['content'] === $tokens[$next]['content']) { + $exceptions = $this->getExceptions( + $phpcsFile, + $tokens[$catch]['parenthesis_opener'] + 1, + $thrownVar - 1 + ); + + foreach ($exceptions as $exception) { + $thrownExceptions[] = $exception; + } + } + } else { + ++$thrownVariables; + } + } + } + + if (! $foundThrows) { + // It should be disabled if we want to declare implicit throws + foreach ($this->throwTags as $ptr => $class) { + $error = 'Function does not throw any exception but has @throw tag'; + $phpcsFile->addError($error, $ptr, 'AdditionalThrowTag'); + } + + return; + } + + // Only need one @throws tag for each type of exception thrown. + $thrownExceptions = array_unique($thrownExceptions); + + // Make sure @throws tag count matches thrown count. + $thrownCount = count($thrownExceptions); + $tagCount = count(array_unique($this->throwTags)); + + if ($thrownVariables > 0) { + if ($thrownCount > $tagCount) { + $error = 'Expected at least %d @throws tag(s) in function comment; %d found'; + $data = [ + $thrownCount, + $tagCount, + ]; + $phpcsFile->addError($error, $stackPtr, 'WrongNumberAtLeast', $data); + return; + } + } else { + if ($thrownCount !== $tagCount) { + $error = 'Expected %d @throws tag(s) in function comment; %d found'; + $data = [ + $thrownCount, + $tagCount, + ]; + $phpcsFile->addError($error, $stackPtr, 'WrongNumberExact', $data); + return; + } + } + + foreach ($thrownExceptions as $throw) { + if (! in_array($throw, $this->throwTags, true)) { + $error = 'Missing @throws tag for "%s" exception'; + $data = [$throw]; + $phpcsFile->addError($error, $stackPtr, 'Missing', $data); + } + } + } + + /** + * @param int $from + * @param int $to + * @return string[] + */ + private function getExceptions(File $phpcsFile, $from, $to) + { + $tokens = $phpcsFile->getTokens(); + + $exceptions = []; + $currName = ''; + $start = null; + $end = null; + + for ($i = $from; $i <= $to; ++$i) { + if (in_array($tokens[$i]['code'], $this->nameTokens, true)) { + if ($currName === '') { + $start = $i; + } + + $end = $i; + $currName .= $tokens[$i]['content']; + } + + if ($tokens[$i]['code'] === T_BITWISE_OR || $i === $to) { + $suggested = $this->getSuggestedType($currName); + + if ($suggested !== $currName) { + $error = 'Invalid exception class name in catch; expected %s, but found %s'; + $data = [ + $suggested, + $currName, + ]; + $fix = $phpcsFile->addFixableError($error, $start, 'InvalidCatchClassName', $data); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($start, $suggested); + for ($j = $start + 1; $j <= $end; ++$j) { + $phpcsFile->fixer->replaceToken($j, ''); + } + $phpcsFile->fixer->endChangeset(); + } + } + + $exceptions[] = $suggested; + $currName = ''; + $start = null; + $end = null; + } + } + + return $exceptions; + } + + /** + * Check if $scope is the last closure/function/try condition. + * + * @param string[] $conditions + * @param int $scope Scope to check in conditions. + * @return bool + */ + private function isLastScope(array $conditions, $scope) + { + foreach (array_reverse($conditions, true) as $ptr => $code) { + if ($code !== T_FUNCTION && $code !== T_CLOSURE && $code !== T_TRY) { + continue; + } + + return $ptr === $scope; + } + + return false; + } +} diff --git a/src/ZendCodingStandard/ruleset.xml b/src/ZendCodingStandard/ruleset.xml index 6364f900..3901581c 100755 --- a/src/ZendCodingStandard/ruleset.xml +++ b/src/ZendCodingStandard/ruleset.xml @@ -72,15 +72,4 @@ - - - - - - - - - - - diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc b/test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc deleted file mode 100644 index 39d80dcb..00000000 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.1.inc +++ /dev/null @@ -1,71 +0,0 @@ - boolean) + * @throws \Exception + * @param $a + * @return void + * @param $b + * @myTag + * @param $c + * @anotherTag + * @throws \RuntimeException + * @param $d */ - private function returnsIntBoolArray() - { - return [1 => true]; - } + private function tagsOrder($a, $b, $c, $d) {} /** - * @return integer[] + * @see */ - private function returnsIntArray() - { - return [0, 1]; - } + private function seeMissingContent() {} /** - * @return boolean[] + * @dataProvider something + * @param int $a + * + * @param int $b Param + * long description. + * + * + * @return void + * + * @throws \Exception */ - private function returnsBoolArray() - { - return [true, false]; - } + private function removeBlankLines($a, $b) {} /** - * @return array() + * @dataProvider something + * + * + * + * @param string $a */ - private function returnsArray() - { - return []; - } + private function toManyEmptyLines($a) {} } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed index f1c72b6e..84daf65b 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed @@ -1,56 +1,51 @@ bool) + * @myTag + * @anotherTag +* + * @param $a + * @param $b + * @param $c + * @param $d + * @return void + * @throws \Exception + * @throws \RuntimeException */ - private function returnsIntBoolArray() - { - return [1 => true]; - } + private function tagsOrder($a, $b, $c, $d) {} /** - * @return int[] + * @see */ - private function returnsIntArray() - { - return [0, 1]; - } + private function seeMissingContent() {} /** - * @return bool[] + * @dataProvider something +* + * @param int $a + * @param int $b Param + * long description. + * @return void + * @throws \Exception */ - private function returnsBoolArray() - { - return [true, false]; - } + private function removeBlankLines($a, $b) {} /** - * @return array + * @dataProvider something + * + * @param string $a */ - private function returnsArray() - { - return []; - } + private function toManyEmptyLines($a) {} } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.php b/test/Sniffs/Commenting/FunctionCommentUnitTest.php index 90eb6e24..16496b29 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.php +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.php @@ -5,34 +5,29 @@ class FunctionCommentUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { - switch ($testFile) { - case 'FunctionCommentUnitTest.1.inc': - return [ - 8 => 2, - 9 => 1, - 17 => 2, - 26 => 1, - 33 => 1, - 35 => 2, - 49 => 1, - 50 => 1, - 57 => 1, - 66 => 1, - ]; - } - return [ - 10 => 1, - 16 => 1, - 26 => 1, - 34 => 1, + 7 => 1, + 11 => 1, + 17 => 1, + 29 => 1, + 35 => 1, + 36 => 1, + 39 => 1, 42 => 1, - 50 => 1, + 49 => 1, ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Functions/ParamUnitTest.inc b/test/Sniffs/Functions/ParamUnitTest.inc new file mode 100644 index 00000000..6d4f9f4c --- /dev/null +++ b/test/Sniffs/Functions/ParamUnitTest.inc @@ -0,0 +1,304 @@ + 1, + 20 => 1, + 23 => 1, + 33 => 1, + 37 => 1, + 40 => 1, + 50 => 3, + 54 => 1, + 57 => 1, + 67 => 1, + 72 => 1, + 77 => 1, + 81 => 1, + 83 => 1, + 85 => 3, + 93 => 1, + 98 => 1, + 103 => 1, + 108 => 1, + 110 => 1, + 113 => 1, + 115 => 1, + 118 => 1, + 123 => 1, + 125 => 1, + 128 => 1, + 129 => 1, + 131 => 1, + 134 => 1, + 138 => 2, + 140 => 2, + 143 => 1, + 144 => 1, + 149 => 1, + 154 => 1, + 155 => 2, + 160 => 1, + 161 => 1, + 162 => 1, + 163 => 1, + 164 => 1, + 165 => 1, + 166 => 1, + 167 => 1, + 172 => 1, + 173 => 1, + 176 => 1, + 177 => 1, + 181 => 1, + 185 => 1, + 188 => 1, + 192 => 1, + 195 => 1, + 200 => 1, + 201 => 1, + 203 => 2, + 207 => 1, + 212 => 1, + 213 => 1, + 214 => 1, + 219 => 1, + 220 => 1, + 221 => 1, + 226 => 1, + 227 => 1, + 232 => 1, + 233 => 1, + 234 => 1, + 235 => 1, + 245 => 1, + 246 => 1, + 247 => 1, + 252 => 1, + 254 => 1, + 255 => 1, + 265 => 1, + 271 => 1, + 272 => 1, + 273 => 1, + 282 => 1, + 290 => 1, + 293 => 1, + 296 => 1, + 301 => 1, + ]; + } + + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') + { + return []; + } +} diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc b/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc new file mode 100644 index 00000000..eaf4d31d --- /dev/null +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc @@ -0,0 +1,403 @@ +method($a) && $a[0]; + } + + /** + * @return array|\DateTime[] + */ + public function returnBoolOnlyHasNonBooleanType4() + { + return ! ['array']; + } + + /** + * @return int + */ + public function returnBoolOnlyHasNonBooleanType5($a) + { + if ($a) { + return true; + } + + return false; + } + + /** + * @return int|string + */ + public function returnPossiblyNotBoolAndDoesNotHaveBoolType($a) + { + return ! $a ? true : null; + } + + /** + * @return bool + */ + public function returnBoolAndHasBooleanType1($a) + { + return ! $a; + } + + /** + * @return boolean + */ + public function returnBoolAndHasBooleanType2($a) + { + return (bool) $a; + } + + public function returnBoolAndHasBooleanReturnType1($a) : bool + { + return ! $a; + } + + public function returnBoolAndHasBooleanReturnType2($a) : ?bool + { + return (bool) $a; + } + + public function returnBoolAndHasBooleanReturnType3($a) : bool + { + if ($a) { + return true; + } + + return false; + } + + public function returnBooleanAndHasNotBooleanReturnType($a) : int + { + if ($a) { + return true; + } + + return 1; + } + + /** + * @return false + */ + public function returnTrueOnlyHasNotTrueValue() + { + return true; + } + + /** + * @return true + */ + public function returnFalseOnlyHasNotFalseValue() + { + return false; + } + + /** + * @return string + */ + public function returnIntAndHasNoIntType1($a) + { + if ($a) { + return 2 * $a; + } + + return 0; + } + + /** + * @return float + */ + public function returnIntAndHasNoIntType2($a) + { + if (! is_float($a)) { + return 1; + } + + return $a; + } + + public function returnIntAndHasNoReturnTypeInt1() : string + { + return 1; + } + + public function returnIntAndHasNoReturnTypeInt2() : float + { + return 1; + } + + public function returnIntAndHasIntReturnType1() : int + { + return 1; + } + + public function returnIntAndHasIntReturnType2() : ?int + { + return 0; + } + + public function returnPossiblyNotIntAndHasIntReturnType($a) : ?int + { + return 5 * $a; + } + + /** + * @return float + */ + public function returnPossiblyNotIntAndDoesNotHaveIntType($a) + { + return 5 * $a; + } + + /** + * @return float + */ + public function returnNullButDoesNotHaveNullType($a) + { + if ($a) { + return $a; + } + + return null; + } + + public function returnNullButReturnTypeIsNotNullable($a) : int + { + if ($a) { + return $a; + } + + return null; + } + + /** + * @return string + */ + public function returnFloatAndHasNoFloatType1($a) + { + if ($a) { + return 2 * $a; + } + + return 0.0; + } + + /** + * @return int + */ + public function returnFloatAndHasNoFloatType2($a) + { + if (! is_int($a)) { + return 1.0; + } + + return $a; + } + + public function returnFloatAndHasNoReturnTypeFloat1() : string + { + return 1.0; + } + + public function returnFloatAndHasNoReturnTypeFloat2() : int + { + return 1.0; + } + + public function returnFloatAndHasFloatReturnType1() : float + { + return 1.0; + } + + public function returnFloatAndHasFloatReturnType2() : ?float + { + return 0.0; + } + + public function returnFloatExpressionAndDoesNotHaveFloatReturnType($a) : ?int + { + return 5.0 * $a; + } + + /** + * @return int + */ + public function returnFloatExpressionAndDoesNotHaveFloatType($a) + { + return 5.0 * $a; + } + + /** + * @return object + */ + public function returnNewInstanceFromVariable($a) + { + return new $a; + } + + /** + * @return OtherClass + */ + public function returnNewInstance() + { + return new MyClass; + } + + /** + * @return MyInterface2 + */ + public function returnTwoDifferentInstances($a) : MyNamespace\MyInterface1 + { + if ($a) { + return new MyNamespace\ClassA(); + } + + return new MyNamespace\ClassX(); + } + + /** + * @return self + */ + public function returnThisOnlyAndHasSelfInTag() + { + return $this; + } + + /** + * @return FunctionCommentReturn + */ + public function returnThisOnlyAndHasClassNameInTag() + { + return $this; + } + + /** + * @return \MyNamespace\Test\Functions\FunctionCommentReturn + */ + public function returnThisOnlyAndHasFCQNClassNameInTag() + { + return $this; + } +} \ No newline at end of file diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.inc b/test/Sniffs/Functions/ReturnTypeUnitTest.inc new file mode 100644 index 00000000..9cfb5d98 --- /dev/null +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.inc @@ -0,0 +1,300 @@ +missingReturnTypeYield($a); + } + + public function returnType() : int + { + return 1; + } + + public function returnTypeYield() : int + { + yield 1; + } + + public function returnTypeYieldFrom() : int + { + yield from $this->returnTypeYieldFrom(); + } + + public function withClosure() + { + $a = function () { + return 1; + }; + } + + public function withClosureYield() + { + $a = function () { + yield 1; + }; + } + + public function withClosureYieldFrom() + { + $a = function () { + yield from $this->returnTypeYield(); + }; + } + + public function returnTypeWithClosure() + { + $a = function (&$x) { + if ($x) { + return; + } + + ++$x; + }; + + return $a; + } + + /** + * @return int + */ + public function invalidReturnTagWithClosure() + { + $a = function () { + return 1; + }; + } + + public function invalidReturnTypeWithClosure() : int + { + $a = function () { + return 1; + }; + } + + public function withAnonClass() + { + $a = new class { + public function a() { + return 1; + } + }; + } + + public function withAnonClassYield() + { + $a = new class { + public function a() { + yield 1; + } + }; + } + + public function withAnonClassYieldFrom() + { + $a = new class { + public function a() { + yield from b(); + } + }; + } + + public function withAnonClassReturnType() + { + $a = new class { + public function a() { + return; + } + }; + + return 1; + } + + /** + * @return int Description. + */ + public function tabSeparatedDoc() + { + return 1; + } + + /** + * @return int Description. + */ + public function moreSpacesInDoc() + { + return 1; + } + + /** + * @return void Description is not allowed. + */ + public function voidWithDescription() {} + + /** + * @return void + */ + public function redundantReturnVoidTag() {} + + /** + * @return int,string + */ + abstract public function invalidTypeNotation(); + + /** + * @return array() + */ + abstract public function invalidTypeNotationArray(); + + /** + * @return array[string] + */ + abstract public function invalidTypeNotationArrayKeys(); + + /** + * @return $This + */ + abstract public function returnThisInvalidCase1(); + + /** + * @return null|$THIS + */ + abstract public function returnThisInvalidCase2(); + + /** + * @return null + */ + abstract public function returnOnlyNull(); + + /** + * @return null[][] + */ + abstract public function returnOnlyNullArray(); + + /** + * @return void|int + */ + abstract public function voidMixedWithOtherTypes(); + + /** + * @return mixed + */ + abstract public function mixedTypeIsNotAllowed(); + + /** + * @return mixed[][] + */ + abstract public function mixedArrayTypeIsNotAllowed(); + + abstract public function returnTypeArrayNeedsSpecification() : array; + + abstract public function returnTypeNullableArrayNeedsSpecification() : ?array; + + abstract public function returnTypeTraversableNeedsSpecification() : \Traversable; + + abstract public function returnTypeNullableTraversableNeedsSpecificaiton() : ?\Traversable; + + abstract public function returnTypeTraversableWithoutNSNeedsSpecification() : Traversable; + + abstract public function returnTypeNullableTraversableWithoutNSNeedsSpecification() : ?Traversable; + + abstract public function returnTypeIterableNeedsSpecification() : iterable; + + abstract public function returnTypeNullableIterableNeedsSpecification() : ?iterable; + + /** + * @return array + */ + abstract public function tagReturnTypeArrayNeedsSpecification(); + + /** + * @return array[] + */ + abstract public function tarReturnTypeArrayOfArraysNeedsSpecification(); + + /** + * @return \Traversable + */ + abstract public function tagReturnTypeTraversableNeedsSpecification(); + + /** + * @return Traversable[] + */ + abstract public function tagReturnTypeArrayOfTraversableNeedsSpecification(); + + /** + * @return iterable + */ + abstract public function tagReturnTypeIterableNeedsSpecification(); + + /** + * @return iterable[] + */ + abstract public function tagReturnTypeArrayOfIterableNeedsSpecification(); + + /** + * @return Array[]|iterable|array|ITerable[][]|Traversable|\traversable[] + */ + abstract public function allTagTypesNeedSpecification(); + + /** + * @return Null|TRUE + */ + public function returnNullOrTrueWrongCaseInTag() + { + return mt_rand(0, 1) ? true : null; + } + + /** + * @return null|False + */ + public function returnNullOrFalseWrongCaseInTag() + { + return mt_rand(0, 1) ? null : false; + } +} diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.php b/test/Sniffs/Functions/ReturnTypeUnitTest.php new file mode 100644 index 00000000..ba3c66e8 --- /dev/null +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.php @@ -0,0 +1,237 @@ + 1, + 16 => 1, + 21 => 1, + 26 => 1, + 31 => 1, + 36 => 1, + 41 => 1, + 46 => 1, + 51 => 2, + 56 => 2, + 61 => 1, + 66 => 1, + 71 => 1, + 76 => 1, + 81 => 1, + 86 => 1, + 91 => 1, + 95 => 1, + 97 => 1, + 100 => 1, + 103 => 1, + 105 => 1, + 107 => 1, + 110 => 1, + 113 => 1, + 115 => 1, + 118 => 1, + 122 => 1, + 125 => 1, + 129 => 1, + 132 => 1, + 137 => 1, + 142 => 1, + 147 => 1, + 152 => 1, + 157 => 1, + 162 => 1, + 167 => 2, + 177 => 1, + 182 => 2, + 192 => 1, + 197 => 2, + 207 => 1, + 212 => 2, + 217 => 1, // in theory we can return here another class of the same parent type... + 222 => 1, + 227 => 2, + // 232 => 1, // There is no error, because return type is invalid + 234 => 1, + 237 => 1, + 242 => 1, + 247 => 2, + 252 => 1, + 262 => 1, + 267 => 1, + 277 => 1, + 282 => 1, + 292 => 1, + 297 => 1, + 302 => 1, + 307 => 2, + // 312 => 1, // There is no error, because return type is invalid + 314 => 1, + 317 => 1, + 322 => 1, + 327 => 2, + 337 => 1, + 342 => 2, + 352 => 1, + 357 => 2, + 362 => 1, + 367 => 1, + 372 => 2, + // 377 => 1, // There is no error, because return type is invalid + 379 => 1, + 382 => 1, + 387 => 2, + 392 => 1, + 397 => 1, + ]; + case 'ReturnTypeUnitTest.2.inc': + return [ + 8 => 3, + 13 => 1, + 18 => 2, + 23 => 1, + 28 => 4, + 33 => 3, + 42 => 1, + 43 => 1, + 44 => 1, + 45 => 1, + 46 => 1, + 47 => 1, + 48 => 1, + 49 => 1, + 50 => 1, + 51 => 1, + 52 => 1, + 53 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 60 => 1, + 61 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 1, + 70 => 1, + 77 => 1, + 84 => 1, + 96 => 1, + 104 => 1, + 108 => 1, + 112 => 1, + 116 => 2, + 124 => 2, + 132 => 1, + 139 => 1, + 148 => 1, + 157 => 1, + 166 => 1, + 176 => 1, + 184 => 1, + 188 => 1, + 192 => 1, + 196 => 1, + 200 => 2, + 204 => 1, + 213 => 1, + 216 => 1, + 236 => 1, + 265 => 1, + 272 => 1, + 276 => 1, + 280 => 1, + 284 => 1, + 296 => 1, + 305 => 1, + 313 => 1, + 318 => 1, + 353 => 1, + 362 => 1, + 374 => 1, + 383 => 1, + 391 => 1, + 396 => 1, + 411 => 1, + 419 => 1, + 431 => 1, + 451 => 1, + 459 => 2, + 467 => 2, + ]; + } + + return [ + 8 => 1, + 10 => 1, + 12 => 1, + 16 => 1, + 18 => 1, + 20 => 1, + 26 => 1, + 32 => 1, + 41 => 1, + 46 => 1, + 51 => 1, + 100 => 1, + 104 => 1, + 113 => 1, + 124 => 1, + 133 => 1, + 142 => 1, + 155 => 1, + 175 => 1, + 180 => 1, + 185 => 1, + 190 => 1, + 195 => 1, + 200 => 1, + 205 => 1, + 210 => 1, + 215 => 1, + 220 => 1, + 225 => 1, + 230 => 1, + 234 => 1, + 236 => 1, + 238 => 1, + 240 => 1, + 242 => 1, + 244 => 1, + 246 => 1, + 248 => 1, + 251 => 1, + 256 => 1, + 261 => 1, + 266 => 1, + 271 => 1, + 276 => 1, + 281 => 6, + 286 => 2, + 294 => 1, + ]; + } + + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') + { + return []; + } +} diff --git a/test/Sniffs/Functions/ThrowsUnitTest.inc b/test/Sniffs/Functions/ThrowsUnitTest.inc new file mode 100644 index 00000000..3a1ba760 --- /dev/null +++ b/test/Sniffs/Functions/ThrowsUnitTest.inc @@ -0,0 +1,273 @@ +getMessage()); + } + } + + /** + * @throws Exception + */ + public function hasThrowsTagsButDoesNotThrowAnything() + { + } + + /** + * @throws Exception + */ + abstract public function abstractCanHaveThrowsTags(); + + public function throwNewClassFromVariable() + { + $e = Exception::class; + throw new $e; + } + + /** + * @throws + */ + public function missingExceptionTypeInTag() + { + } + + public function throwVariableAndException() + { + $e = new Exception(); + throw $e; + throw new Exception(); + } + + /** + * @throws Exception + */ + public function throwVariableAndExceptionOK1() + { + $e = ExceptionFactory::createException(); + throw $e; + throw new Exception(); + } + + /** + * @throws Ex + * @throws Exception + */ + public function throwVariableAndExceptionOK2() + { + $e = ExceptionFactory::createException(); + throw $e; + throw new Exception(); + } + + /** + * @throws Exception + * @throws Ex + * @throws \InvalidArgumentException + */ + public function valid1() + { + throw new Ex(); + throw new Exception(); + throw new Ex(); + throw new \InvalidArgumentException(); + throw new Exception(); + } + + public function valid2() + { + try { + throw new Ex(); + } catch (Exception $e) { + } + } + + public function valid3() + { + return function() { + throw new Ex(); + }; + } + + /** + * @throws UnknownExceptionType + */ + public function valid4() + { + throw $this->throwException(); + } + + /** + * @throws UnknownException It cannot be determined. + */ + public function valid5() + { + $ex = ExceptionFactory::create(); + throw $ex; + } + + public function valid6() + { + return function () { + return new class { + /** + * @throws Exception + */ + public function x() { + throw new Exception(); + } + }; + }; + } + + abstract public function abstractMethod(); +} diff --git a/test/Sniffs/Functions/ThrowsUnitTest.php b/test/Sniffs/Functions/ThrowsUnitTest.php new file mode 100644 index 00000000..0c8566b2 --- /dev/null +++ b/test/Sniffs/Functions/ThrowsUnitTest.php @@ -0,0 +1,42 @@ + 1, + 18 => 1, + 28 => 1, + 40 => 1, + 46 => 1, + 50 => 1, + 60 => 2, + 68 => 1, + 78 => 1, + 97 => 1, + 127 => 1, + 142 => 1, + 160 => 1, + 174 => 1, + 178 => 1, + 184 => 1, + ]; + } + + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') + { + return []; + } +} From 3019fbd394a5c3c09e5974266a3cb6a225e39a3a Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 18:39:34 +0100 Subject: [PATCH 145/225] Updated comments for methods to pass with new sniffs --- src/ZendCodingStandard/CodingStandard.php | 2 -- .../Sniffs/Arrays/FormatSniff.php | 8 ++--- .../Sniffs/Arrays/TrailingArrayCommaSniff.php | 4 +-- .../AlphabeticallySortedTraitsSniff.php | 16 ++++----- .../Sniffs/Classes/NoNullValuesSniff.php | 6 ++-- .../Sniffs/Classes/TraitUsageSniff.php | 12 +++---- .../Sniffs/Commenting/DocCommentSniff.php | 35 +++++-------------- .../Commenting/VariableCommentSniff.php | 6 ++-- .../Sniffs/Formatting/DoubleColonSniff.php | 4 +-- .../Sniffs/Formatting/NewKeywordSniff.php | 4 +-- .../Formatting/NoSpaceAfterSplatSniff.php | 4 +-- .../Sniffs/Formatting/ReferenceSniff.php | 4 +-- .../Sniffs/Formatting/ReturnTypeSniff.php | 10 ++---- .../UnnecessaryParenthesesSniff.php | 6 ++-- .../Sniffs/Methods/LineAfterSniff.php | 8 ++--- .../AlphabeticallySortedUsesSniff.php | 15 ++++---- .../ConstAndFunctionKeywordsSniff.php | 4 +-- .../Namespaces/UnusedUseStatementSniff.php | 6 ++-- .../UseDoesNotStartWithBackslashSniff.php | 4 +-- .../ValidVariableNameSniff.php | 6 ++-- .../Sniffs/Operators/BooleanOperatorSniff.php | 4 +-- .../Sniffs/Operators/TernaryOperatorSniff.php | 10 +++--- .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 23 ++---------- .../PHP/ImportInternalConstantSniff.php | 5 ++- .../PHP/ImportInternalFunctionSniff.php | 5 ++- .../PHP/InstantiatingParenthesisSniff.php | 4 +-- .../Sniffs/PHP/LowerCaseKeywordSniff.php | 2 +- .../Sniffs/PHP/RedundantSemicolonSniff.php | 4 +-- .../Sniffs/PHP/TypeCastingSniff.php | 4 +-- .../Strings/NoConcatenationAtTheEndSniff.php | 4 +-- .../Sniffs/WhiteSpace/BlankLineSniff.php | 4 +-- .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 4 +-- .../WhiteSpace/NoBlankLineAtStartSniff.php | 4 +-- .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 18 ++++------ test/Ruleset.php | 5 +++ test/Sniffs/Arrays/FormatUnitTest.php | 12 +++++-- .../Arrays/TrailingArrayCommaUnitTest.php | 12 +++++-- .../AlphabeticallySortedTraitsUnitTest.php | 12 +++++-- test/Sniffs/Classes/NoNullValuesUnitTest.php | 12 +++++-- test/Sniffs/Classes/TraitUsageUnitTest.php | 12 +++++-- test/Sniffs/Commenting/DocCommentUnitTest.php | 8 +++++ .../Sniffs/Formatting/DoubleColonUnitTest.php | 8 +++++ test/Sniffs/Formatting/NewKeywordUnitTest.php | 8 +++++ .../Formatting/NoSpaceAfterSplatUnitTest.php | 8 +++++ test/Sniffs/Formatting/ReferenceUnitTest.php | 8 +++++ test/Sniffs/Formatting/ReturnTypeUnitTest.php | 8 +++++ .../UnnecessaryParenthesesUnitTest.php | 8 +++++ test/Sniffs/Methods/LineAfterUnitTest.php | 8 +++++ .../AlphabeticallySortedUsesUnitTest.php | 8 +++++ .../ConstAndFunctionKeywordsUnitTest.php | 8 +++++ .../Namespaces/UnusedUseStatementUnitTest.php | 12 +++++-- .../UseDoesNotStartWithBackslashUnitTest.php | 8 +++++ .../ValidVariableNameUnitTest.php | 8 +++++ .../Operators/BooleanOperatorUnitTest.php | 8 +++++ .../Operators/TernaryOperatorUnitTest.php | 8 +++++ .../PHP/CorrectClassNameCaseUnitTest.php | 8 +++++ .../PHP/ImportInternalConstantUnitTest.php | 8 +++++ .../PHP/ImportInternalFunctionUnitTest.php | 8 +++++ .../PHP/InstantiatingParenthesisUnitTest.php | 8 +++++ test/Sniffs/PHP/LowerCaseKeywordUnitTest.php | 8 +++++ .../Sniffs/PHP/RedundantSemicolonUnitTest.php | 8 +++++ test/Sniffs/PHP/TypeCastingUnitTest.php | 8 +++++ .../NoConcatenationAtTheEndUnitTest.php | 8 +++++ test/Sniffs/TestCase.php | 12 +++---- test/Sniffs/WhiteSpace/BlankLineUnitTest.php | 8 +++++ .../WhiteSpace/CommaSpacingUnitTest.php | 8 +++++ .../WhiteSpace/NoBlankLineAtStartUnitTest.php | 8 +++++ .../Sniffs/WhiteSpace/ScopeIndentUnitTest.php | 8 +++++ 68 files changed, 373 insertions(+), 183 deletions(-) diff --git a/src/ZendCodingStandard/CodingStandard.php b/src/ZendCodingStandard/CodingStandard.php index 1835c637..a8486ee5 100644 --- a/src/ZendCodingStandard/CodingStandard.php +++ b/src/ZendCodingStandard/CodingStandard.php @@ -76,7 +76,6 @@ public static function suggestType($varType) } /** - * @param File $phpcsFile * @param int $stackPtr * @return bool */ @@ -99,7 +98,6 @@ public static function isTraitUse(File $phpcsFile, $stackPtr) } /** - * @param File $phpcsFile * @param int $stackPtr * @return bool */ diff --git a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index 93151d9b..1038bc56 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -24,7 +24,7 @@ class FormatSniff implements Sniff public $indent = 4; /** - * @inheritDoc + * @return int[] */ public function register() { @@ -32,7 +32,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { @@ -51,9 +51,7 @@ public function process(File $phpcsFile, $stackPtr) } /** - * @param File $phpcsFile * @param int $stackPtr - * @return void */ private function multiLineArray(File $phpcsFile, $stackPtr) { @@ -164,9 +162,7 @@ private function multiLineArray(File $phpcsFile, $stackPtr) } /** - * @param File $phpcsFile * @param int $stackPtr - * @return void */ private function singleLineArray(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php index 7ded102c..8e6467d7 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php @@ -24,7 +24,7 @@ class TrailingArrayCommaSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -32,7 +32,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php index ca63f1fe..7ae6a2a9 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php @@ -26,7 +26,7 @@ class AlphabeticallySortedTraitsSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -34,7 +34,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { @@ -66,9 +66,8 @@ public function process(File $phpcsFile, $stackPtr) } /** - * @param File $phpcsFile * @param int $scopePtr - * @return array[] + * @return string[][] */ private function getTraits(File $phpcsFile, $scopePtr) { @@ -110,7 +109,6 @@ private function getTraits(File $phpcsFile, $scopePtr) } /** - * @param File $phpcsFile * @param int $stackPtr * @return int */ @@ -130,8 +128,8 @@ private function getEndOfTraitScope(File $phpcsFile, $stackPtr) } /** - * @param array $a - * @param array $b + * @param string[] $a + * @param string[] $b * @return int */ private function compareUseStatements(array $a, array $b) @@ -152,9 +150,7 @@ private function clearName($name) } /** - * @param File $phpcsFile - * @param array[] $uses - * @return void + * @param string[][] $uses */ private function fixAlphabeticalOrder(File $phpcsFile, array $uses) { diff --git a/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php b/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php index 224bb605..713b01c8 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php @@ -14,7 +14,7 @@ class NoNullValuesSniff extends AbstractVariableSniff { /** - * @inheritDoc + * @param int $stackPtr */ protected function processMemberVar(File $phpcsFile, $stackPtr) { @@ -45,7 +45,7 @@ protected function processMemberVar(File $phpcsFile, $stackPtr) } /** - * @inheritDoc + * @param int $stackPtr */ protected function processVariable(File $phpcsFile, $stackPtr) { @@ -53,7 +53,7 @@ protected function processVariable(File $phpcsFile, $stackPtr) } /** - * @inheritDoc + * @param int $stackPtr */ protected function processVariableInString(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php index 519e46df..0ee1a491 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php @@ -25,7 +25,7 @@ class TraitUsageSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -33,7 +33,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { @@ -275,9 +275,7 @@ public function process(File $phpcsFile, $stackPtr) /** * Fix order of statements inside trait's curly brackets. * - * @param File $phpcsFile - * @param array $statements - * @return void + * @param string[] $statements */ private function fixAlphabeticalOrder(File $phpcsFile, array $statements) { @@ -303,8 +301,8 @@ private function fixAlphabeticalOrder(File $phpcsFile, array $statements) /** * @internal * - * @param array $a - * @param array $b + * @param string[] $a + * @param string[] $b * @return int */ public function compareStatements(array $a, array $b) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index 28b2f5df..d078b85a 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -32,8 +32,14 @@ class DocCommentSniff implements Sniff { + /** + * @var int + */ public $indent = 4; + /** + * @var string[] + */ public $tagWithType = [ '@var', '@param', @@ -42,7 +48,7 @@ class DocCommentSniff implements Sniff ]; /** - * @inheritDoc + * @return int[] */ public function register() { @@ -50,7 +56,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { @@ -86,7 +92,6 @@ public function process(File $phpcsFile, $stackPtr) /** * Checks if doc comment is empty. * - * @param File $phpcsFile * @param int $commentStart * @param int $commentEnd * @return bool @@ -152,9 +157,7 @@ private function checkIfEmpty(File $phpcsFile, $commentStart, $commentEnd) * Checks if there is no any other content before doc comment opening tag, * and if there is blank line before doc comment (for multiline doc comment). * - * @param File $phpcsFile * @param int $commentStart - * @return void */ private function checkBeforeOpen(File $phpcsFile, $commentStart) { @@ -192,9 +195,7 @@ private function checkBeforeOpen(File $phpcsFile, $commentStart) /** * Checks if there is no any other content after doc comment opening tag (for multiline doc comment). * - * @param File $phpcsFile * @param int $commentStart - * @return void */ private function checkAfterOpen(File $phpcsFile, $commentStart) { @@ -231,9 +232,7 @@ private function checkAfterOpen(File $phpcsFile, $commentStart) /** * Checks if there is no any other content before doc comment closing tag (for multiline doc comment). * - * @param File $phpcsFile * @param int $commentEnd - * @return void */ private function checkBeforeClose(File $phpcsFile, $commentEnd) { @@ -259,10 +258,8 @@ private function checkBeforeClose(File $phpcsFile, $commentEnd) /** * Checks if there is no any other content after doc comment closing tag (for multiline doc comment). * - * @param File $phpcsFile * @param int $commentStart * @param int $commentEnd - * @return void */ private function checkAfterClose(File $phpcsFile, $commentStart, $commentEnd) { @@ -329,10 +326,8 @@ private function checkAfterClose(File $phpcsFile, $commentStart, $commentEnd) * Checks if there is exactly one space after doc comment opening tag, * and exactly one space before closing tag (for single line doc comment). * - * @param File $phpcsFile * @param int $commentStart * @param int $commentEnd - * @return void */ private function checkSpacesInOneLineComment(File $phpcsFile, $commentStart, $commentEnd) { @@ -351,7 +346,7 @@ private function checkSpacesInOneLineComment(File $phpcsFile, $commentStart, $co } elseif ($tokens[$commentStart + 1]['code'] !== T_DOC_COMMENT_WHITESPACE) { // This case is currently not supported. // Comment /**@var null $name; */ is not recognized as doc-block comment. - // todo: fix is already marged to PHP_CodeSniffer 3.1.0, need to be changed after release 3.1.0 + // todo: fix is already merged to PHP_CodeSniffer 3.1.0, need to be changed after release 3.1.0 $error = 'Expected 1 space after opening tag of one line doc block comment.'; $fix = $phpcsFile->addFixableError($error, $commentStart, 'InvalidSpacing'); @@ -378,10 +373,8 @@ private function checkSpacesInOneLineComment(File $phpcsFile, $commentStart, $co * * @todo: needs to check with doctrine annotations * - * @param File $phpcsFile * @param int $commentStart * @param int $commentEnd - * @return void */ private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEnd) { @@ -479,10 +472,8 @@ private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEn * Doc comment cannot have empty line on the beginning of the comment, at the end of the comment, * and there is allowed only one empty line between two comment sections. * - * @param File $phpcsFile * @param int $commentStart * @param int $commentEnd - * @return void */ private function checkBlankLinesInComment(File $phpcsFile, $commentStart, $commentEnd) { @@ -584,10 +575,8 @@ private function checkBlankLinesInComment(File $phpcsFile, $commentStart, $comme /** * Checks indents of the comment (opening tag, lines with star, closing tag). * - * @param File $phpcsFile * @param int $commentStart * @param int $commentEnd - * @return void */ private function checkCommentIndents(File $phpcsFile, $commentStart, $commentEnd) { @@ -704,9 +693,7 @@ private function checkCommentIndents(File $phpcsFile, $commentStart, $commentEnd /** * Check if there is one blank line before comment tags. * - * @param File $phpcsFile * @param int $commentStart - * @return void */ private function checkBlankLineBeforeTags(File $phpcsFile, $commentStart) { @@ -742,9 +729,7 @@ private function checkBlankLineBeforeTags(File $phpcsFile, $commentStart) } /** - * @param File $phpcsFile * @param int $commentStart - * @return void */ private function checkTagsSpaces(File $phpcsFile, $commentStart) { @@ -802,9 +787,7 @@ private function checkTagsSpaces(File $phpcsFile, $commentStart) } /** - * @param File $phpcsFile * @param int $tag - * @return void */ private function checkSpacesAfterTag(File $phpcsFile, $tag) { diff --git a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php index c0d86481..41cfc439 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php @@ -25,7 +25,7 @@ class VariableCommentSniff extends AbstractVariableSniff { /** - * @inheritDoc + * @param int $stackPtr */ public function processMemberVar(File $phpcsFile, $stackPtr) { @@ -121,7 +121,7 @@ public function processMemberVar(File $phpcsFile, $stackPtr) } /** - * @inheritDoc + * @param int $stackPtr */ protected function processVariable(File $phpcsFile, $stackPtr) { @@ -129,7 +129,7 @@ protected function processVariable(File $phpcsFile, $stackPtr) } /** - * @inheritDoc + * @param int $stackPtr */ protected function processVariableInString(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php index 0effecc2..f20c9b5e 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php @@ -10,7 +10,7 @@ class DoubleColonSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -18,7 +18,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php index 12cc3223..dc18ae7a 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php @@ -10,7 +10,7 @@ class NewKeywordSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -18,7 +18,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php index ce6b274c..8d35c3d3 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php @@ -10,7 +10,7 @@ class NoSpaceAfterSplatSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -18,7 +18,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php index 35df9429..01583e4e 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php @@ -16,7 +16,7 @@ class ReferenceSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -24,7 +24,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php index 33ae9995..ed147e62 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php @@ -55,7 +55,7 @@ class ReturnTypeSniff implements Sniff ]; /** - * @inheritDoc + * @return int[] */ public function register() { @@ -63,7 +63,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { @@ -141,9 +141,7 @@ public function process(File $phpcsFile, $stackPtr) /** * Check if token before colon match configured number of spaces. * - * @param File $phpcsFile * @param int $colon - * @return void */ private function checkSpacesBeforeColon(File $phpcsFile, $colon) { @@ -189,9 +187,7 @@ private function checkSpacesBeforeColon(File $phpcsFile, $colon) /** * Check if token after colon match configured number of spaces. * - * @param File $phpcsFile * @param int $colon - * @return void */ private function checkSpacesAfterColon(File $phpcsFile, $colon) { @@ -230,9 +226,7 @@ private function checkSpacesAfterColon(File $phpcsFile, $colon) /** * Checks if token after nullable operator match configured number of spaces. * - * @param File $phpcsFile * @param int $nullable - * @return void */ private function checkSpacesAfterNullable(File $phpcsFile, $nullable) { diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php index b1dc9e41..9cdde574 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -93,7 +93,7 @@ class UnnecessaryParenthesesSniff implements Sniff ]; /** - * @inheritDoc + * @return int[] */ public function register() { @@ -101,7 +101,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { @@ -245,11 +245,9 @@ public function process(File $phpcsFile, $stackPtr) } /** - * @param File $phpcsFile * @param int $openPtr * @param int $closePtr * @param string $errorCode - * @return void */ private function error(File $phpcsFile, $openPtr, $closePtr, $errorCode) { diff --git a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php index 916d681e..10322b1d 100644 --- a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php +++ b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php @@ -17,16 +17,14 @@ class LineAfterSniff extends AbstractScopeSniff { - /** - * @inheritDoc - */ public function __construct() { parent::__construct([T_CLASS, T_INTERFACE, T_TRAIT, T_ANON_CLASS], [T_FUNCTION]); } /** - * @inheritDoc + * @param int $stackPtr + * @param int $currScope */ protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) { @@ -64,7 +62,7 @@ protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScop } /** - * @inheritDoc + * @param int $stackPtr */ protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php index 9f58f46d..f641258e 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -24,7 +24,7 @@ class AlphabeticallySortedUsesSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -32,7 +32,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { @@ -130,9 +130,8 @@ public function process(File $phpcsFile, $stackPtr) } /** - * @param File $phpcsFile * @param int $scopePtr - * @return array[] + * @return string[][] */ private function getUseStatements(File $phpcsFile, $scopePtr) { @@ -189,8 +188,8 @@ private function getUseStatements(File $phpcsFile, $scopePtr) } /** - * @param array $a - * @param array $b + * @param string[] $a + * @param string[] $b * @return int */ private function compareUseStatements(array $a, array $b) @@ -221,9 +220,7 @@ private function clearName($name) } /** - * @param File $phpcsFile - * @param array[] $uses - * @return void + * @param string[][] $uses */ private function fixAlphabeticalOrder(File $phpcsFile, array $uses) { diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php index ec7ec8d0..1abce351 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php @@ -14,7 +14,7 @@ class ConstAndFunctionKeywordsSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -22,7 +22,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index 67958ca0..ca367141 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -41,7 +41,7 @@ class UnusedUseStatementSniff implements Sniff { /** - * @var array + * @var int[] */ private $checkInTokens = [ T_STRING, @@ -51,7 +51,7 @@ class UnusedUseStatementSniff implements Sniff ]; /** - * @inheritDoc + * @return int[] */ public function register() { @@ -59,7 +59,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php index e1473861..4ab895e3 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php @@ -16,7 +16,7 @@ class UseDoesNotStartWithBackslashSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -24,7 +24,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php index 20430b72..0e1f31a7 100644 --- a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php +++ b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -35,7 +35,7 @@ class ValidVariableNameSniff extends AbstractVariableSniff ]; /** - * @inheritDoc + * @param int $stackPtr */ protected function processVariable(File $phpcsFile, $stackPtr) { @@ -60,7 +60,7 @@ protected function processVariable(File $phpcsFile, $stackPtr) } /** - * @inheritDoc + * @param int $stackPtr */ protected function processMemberVar(File $phpcsFile, $stackPtr) { @@ -68,7 +68,7 @@ protected function processMemberVar(File $phpcsFile, $stackPtr) } /** - * @inheritDoc + * @param int $stackPtr */ protected function processVariableInString(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php b/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php index c6151da7..e2847f27 100644 --- a/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php +++ b/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php @@ -10,7 +10,7 @@ class BooleanOperatorSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -18,7 +18,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php b/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php index a8efec50..bccd54ab 100644 --- a/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php +++ b/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php @@ -12,7 +12,7 @@ class TernaryOperatorSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -23,7 +23,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { @@ -90,9 +90,8 @@ public function process(File $phpcsFile, $stackPtr) } /** - * @param File $phpcsFile * @param int $stackPtr - * @return int|null + * @return null|int */ protected function findThen(File $phpcsFile, $stackPtr) { @@ -116,9 +115,8 @@ protected function findThen(File $phpcsFile, $stackPtr) } /** - * @param File $phpcsFile * @param int $stackPtr - * @return int|null + * @return null|int */ protected function findElse(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index 14db0fbc..6b873329 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -69,7 +69,7 @@ public function __construct() } /** - * @inheritDoc + * @return int[] */ public function register() { @@ -90,7 +90,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { @@ -124,9 +124,7 @@ public function process(File $phpcsFile, $stackPtr) /** * Checks statement before double colon - "ClassName::". * - * @param File $phpcsFile * @param int $stackPtr - * @return void */ private function checkDoubleColon(File $phpcsFile, $stackPtr) { @@ -156,9 +154,7 @@ private function checkDoubleColon(File $phpcsFile, $stackPtr) /** * Checks "new ClassName" statements. * - * @param File $phpcsFile * @param int $stackPtr - * @return void */ private function checkNew(File $phpcsFile, $stackPtr) { @@ -187,9 +183,7 @@ private function checkNew(File $phpcsFile, $stackPtr) /** * Checks "use" statements - global and traits. * - * @param File $phpcsFile * @param int $stackPtr - * @return void */ private function checkUse(File $phpcsFile, $stackPtr) { @@ -223,9 +217,7 @@ private function checkUse(File $phpcsFile, $stackPtr) /** * Checks params type hints * - * @param File $phpcsFile * @param int $stackPtr - * @return void */ private function checkFunctionParams(File $phpcsFile, $stackPtr) { @@ -247,9 +239,7 @@ private function checkFunctionParams(File $phpcsFile, $stackPtr) /** * Checks return type (PHP 7) * - * @param File $phpcsFile * @param int $stackPtr - * @return void */ private function checkReturnType(File $phpcsFile, $stackPtr) { @@ -262,9 +252,7 @@ private function checkReturnType(File $phpcsFile, $stackPtr) /** * Checks PHPDocs tags * - * @param File $phpcsFile * @param int $stackPtr - * @return void */ private function checkTag(File $phpcsFile, $stackPtr) { @@ -310,7 +298,6 @@ private function checkTag(File $phpcsFile, $stackPtr) /** * Returns expected class name for given $class. * - * @param File $phpcsFile * @param string $class * @param int $stackPtr * @return string @@ -350,9 +337,7 @@ private function getExpectedName(File $phpcsFile, $class, $stackPtr) /** * Checks "extends" and "implements" classes/interfaces. * - * @param File $phpcsFile * @param int $stackPtr - * @return void */ private function checkExtendsAndImplements(File $phpcsFile, $stackPtr) { @@ -382,11 +367,9 @@ private function checkExtendsAndImplements(File $phpcsFile, $stackPtr) /** * Checks if class is used correctly. * - * @param File $phpcsFile * @param int $start * @param int $end * @param bool $isGlobalUse - * @return void */ private function checkClass(File $phpcsFile, $start, $end, $isGlobalUse = false) { @@ -430,12 +413,10 @@ private function checkClass(File $phpcsFile, $start, $end, $isGlobalUse = false) /** * Reports new fixable error. * - * @param File $phpcsFile * @param int $start * @param int $end * @param string $expected * @param string $actual - * @return void */ private function error(File $phpcsFile, $start, $end, $expected, $actual) { diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php index a49fe9ef..48654823 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php @@ -67,7 +67,7 @@ public function __construct() } /** - * @inheritDoc + * @return int[] */ public function register() { @@ -75,7 +75,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { @@ -167,7 +167,6 @@ public function process(File $phpcsFile, $stackPtr) } /** - * @param File $phpcsFile * @param int $stackPtr * @param string $constantName */ diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php index 4c1fdf08..d2b57925 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php @@ -58,7 +58,7 @@ public function __construct() } /** - * @inheritDoc + * @return int[] */ public function register() { @@ -66,7 +66,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { @@ -155,7 +155,6 @@ public function process(File $phpcsFile, $stackPtr) } /** - * @param File $phpcsFile * @param int $stackPtr * @param string $functionName */ diff --git a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php index 54fbb94f..3b05b834 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php @@ -19,7 +19,7 @@ class InstantiatingParenthesisSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -27,7 +27,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php b/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php index b7dbbd6d..b14d185f 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php @@ -13,7 +13,7 @@ class LowerCaseKeywordSniff extends GenericLowerCaseKeywordSniff { /** - * @inheritDoc + * @return int[] */ public function register() { diff --git a/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php b/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php index 3e6708ee..1c101695 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php @@ -16,7 +16,7 @@ class RedundantSemicolonSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -24,7 +24,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php index 6f37d402..b8cca764 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -22,7 +22,7 @@ class TypeCastingSniff implements Sniff ]; /** - * @inheritDoc + * @return int[] */ public function register() { @@ -31,7 +31,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php b/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php index 2cf7a3c9..a322f8ed 100644 --- a/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php +++ b/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php @@ -10,7 +10,7 @@ class NoConcatenationAtTheEndSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -18,7 +18,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php index d4da4346..cb824201 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php @@ -11,7 +11,7 @@ class BlankLineSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -23,7 +23,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index 498d645d..e620f844 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -31,7 +31,7 @@ class CommaSpacingSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -39,7 +39,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php index be1ea88c..7fed9c56 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php @@ -14,7 +14,7 @@ class NoBlankLineAtStartSniff implements Sniff { /** - * @inheritDoc + * @return int[] */ public function register() { @@ -28,7 +28,7 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr */ public function process(File $phpcsFile, $stackPtr) { diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index 11f1864b..8e04637f 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -133,7 +133,7 @@ public function __construct() } /** - * @inheritDoc + * @return int[] */ public function register() { @@ -141,7 +141,8 @@ public function register() } /** - * @inheritDoc + * @param int $stackPtr + * @return null|int */ public function process(File $phpcsFile, $stackPtr) { @@ -715,9 +716,8 @@ public function process(File $phpcsFile, $stackPtr) /** * @todo: need name refactor and method description * - * @param File $phpcsFile * @param int $ptr - * @return int|null + * @return null|int */ private function fp(File $phpcsFile, $ptr) { @@ -743,9 +743,8 @@ private function fp(File $phpcsFile, $ptr) /** * @todo: need name refactor and method description * - * @param File $phpcsFile * @param int $ptr - * @return int|null + * @return null|int */ private function np(File $phpcsFile, $ptr) { @@ -770,9 +769,8 @@ private function np(File $phpcsFile, $ptr) * Checks if there is another object operator * before $ptr token. * - * @param File $phpcsFile * @param int $ptr - * @return int|null + * @return null|int */ private function hasPrevObjectOperator(File $phpcsFile, $ptr) { @@ -797,7 +795,6 @@ private function hasPrevObjectOperator(File $phpcsFile, $ptr) * Checks if between $fromPtr and $toPtr is any new line * excluding scopes (arrays, closures, multiline function calls). * - * @param File $phpcsFile * @param int $fromPtr * @param int $toPtr * @return bool @@ -835,9 +832,8 @@ private function hasContainNewLine(File $phpcsFile, $fromPtr, $toPtr) * and returns the control structure pointer; * otherwise returns boolean `false`. * - * @param File $phpcsFile * @param int $ptr - * @return int|false + * @return false|int */ private function getControlStructurePtr(File $phpcsFile, $ptr) { diff --git a/test/Ruleset.php b/test/Ruleset.php index a355eae8..99a669f2 100644 --- a/test/Ruleset.php +++ b/test/Ruleset.php @@ -5,6 +5,11 @@ class Ruleset extends \PHP_CodeSniffer\Ruleset { + /** + * @param string[] $files + * @param bool[] $restrictions + * @param bool[] $exclusions + */ public function registerSniffs($files, $restrictions, $exclusions) { foreach ($restrictions as $className => $bool) { diff --git a/test/Sniffs/Arrays/FormatUnitTest.php b/test/Sniffs/Arrays/FormatUnitTest.php index 6c82d0fd..8ac2246d 100644 --- a/test/Sniffs/Arrays/FormatUnitTest.php +++ b/test/Sniffs/Arrays/FormatUnitTest.php @@ -5,7 +5,11 @@ class FormatUnitTest extends TestCase { - public function getErrorList() + /** + * @param string $testFile + * @return int[] + */ + public function getErrorList($testFile = '') { return [ 2 => 2, @@ -34,7 +38,11 @@ public function getErrorList() ]; } - public function getWarningList() + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') { return []; } diff --git a/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.php b/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.php index 24a851b2..e2215c34 100644 --- a/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.php +++ b/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.php @@ -5,7 +5,11 @@ class TrailingArrayCommaUnitTest extends TestCase { - public function getErrorList() + /** + * @param string $testFile + * @return int[] + */ + public function getErrorList($testFile = '') { return [ 11 => 1, @@ -15,7 +19,11 @@ public function getErrorList() ]; } - public function getWarningList() + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') { return []; } diff --git a/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.php b/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.php index 9ff07965..eff06166 100644 --- a/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.php +++ b/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.php @@ -5,7 +5,11 @@ class AlphabeticallySortedTraitsUnitTest extends TestCase { - public function getErrorList() + /** + * @param string $testFile + * @return int[] + */ + public function getErrorList($testFile = '') { return [ 12 => 1, @@ -13,7 +17,11 @@ public function getErrorList() ]; } - public function getWarningList() + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') { return []; } diff --git a/test/Sniffs/Classes/NoNullValuesUnitTest.php b/test/Sniffs/Classes/NoNullValuesUnitTest.php index e390b919..9ad06884 100644 --- a/test/Sniffs/Classes/NoNullValuesUnitTest.php +++ b/test/Sniffs/Classes/NoNullValuesUnitTest.php @@ -5,7 +5,11 @@ class NoNullValuesUnitTest extends TestCase { - public function getErrorList() + /** + * @param string $testFile + * @return int[] + */ + public function getErrorList($testFile = '') { return [ 6 => 1, @@ -19,7 +23,11 @@ public function getErrorList() ]; } - public function getWarningList() + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') { return []; } diff --git a/test/Sniffs/Classes/TraitUsageUnitTest.php b/test/Sniffs/Classes/TraitUsageUnitTest.php index 51ee187f..4fec3eca 100644 --- a/test/Sniffs/Classes/TraitUsageUnitTest.php +++ b/test/Sniffs/Classes/TraitUsageUnitTest.php @@ -5,7 +5,11 @@ class TraitUsageUnitTest extends TestCase { - public function getErrorList() + /** + * @param string $testFile + * @return int[] + */ + public function getErrorList($testFile = '') { return [ 9 => 1, @@ -21,7 +25,11 @@ public function getErrorList() ]; } - public function getWarningList() + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') { return []; } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.php b/test/Sniffs/Commenting/DocCommentUnitTest.php index 5e8be254..770e8c29 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.php +++ b/test/Sniffs/Commenting/DocCommentUnitTest.php @@ -5,6 +5,10 @@ class DocCommentUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { switch ($testFile) { @@ -154,6 +158,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Formatting/DoubleColonUnitTest.php b/test/Sniffs/Formatting/DoubleColonUnitTest.php index 19a2f1ec..6f96b7f9 100644 --- a/test/Sniffs/Formatting/DoubleColonUnitTest.php +++ b/test/Sniffs/Formatting/DoubleColonUnitTest.php @@ -5,6 +5,10 @@ class DoubleColonUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -18,6 +22,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Formatting/NewKeywordUnitTest.php b/test/Sniffs/Formatting/NewKeywordUnitTest.php index 44455c4c..3b617d1d 100644 --- a/test/Sniffs/Formatting/NewKeywordUnitTest.php +++ b/test/Sniffs/Formatting/NewKeywordUnitTest.php @@ -5,6 +5,10 @@ class NewKeywordUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -18,6 +22,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Formatting/NoSpaceAfterSplatUnitTest.php b/test/Sniffs/Formatting/NoSpaceAfterSplatUnitTest.php index 9f8ee5bc..9ed68254 100644 --- a/test/Sniffs/Formatting/NoSpaceAfterSplatUnitTest.php +++ b/test/Sniffs/Formatting/NoSpaceAfterSplatUnitTest.php @@ -5,6 +5,10 @@ class NoSpaceAfterSplatUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -16,6 +20,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Formatting/ReferenceUnitTest.php b/test/Sniffs/Formatting/ReferenceUnitTest.php index 6b676a19..96c1a7f1 100644 --- a/test/Sniffs/Formatting/ReferenceUnitTest.php +++ b/test/Sniffs/Formatting/ReferenceUnitTest.php @@ -5,6 +5,10 @@ class ReferenceUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -17,6 +21,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Formatting/ReturnTypeUnitTest.php b/test/Sniffs/Formatting/ReturnTypeUnitTest.php index 7256d6e9..5b456336 100644 --- a/test/Sniffs/Formatting/ReturnTypeUnitTest.php +++ b/test/Sniffs/Formatting/ReturnTypeUnitTest.php @@ -5,6 +5,10 @@ class ReturnTypeUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { if ($testFile === 'ReturnTypeUnitTest.1.inc') { @@ -60,6 +64,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php index f72b45bf..2df86767 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php @@ -5,6 +5,10 @@ class UnnecessaryParenthesesUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -52,6 +56,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Methods/LineAfterUnitTest.php b/test/Sniffs/Methods/LineAfterUnitTest.php index 2085b70f..2965be78 100644 --- a/test/Sniffs/Methods/LineAfterUnitTest.php +++ b/test/Sniffs/Methods/LineAfterUnitTest.php @@ -5,6 +5,10 @@ class LineAfterUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { switch ($testFile) { @@ -48,6 +52,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php index 45ddd722..b69deb5a 100644 --- a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php +++ b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php @@ -5,6 +5,10 @@ class AlphabeticallySortedUsesUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { switch ($testFile) { @@ -25,6 +29,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.php b/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.php index 421f3e9c..8444b863 100644 --- a/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.php +++ b/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.php @@ -5,6 +5,10 @@ class ConstAndFunctionKeywordsUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -15,6 +19,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.php b/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.php index 5aecfa18..b52826a2 100644 --- a/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.php +++ b/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.php @@ -5,12 +5,20 @@ class UnusedUseStatementUnitTest extends TestCase { - public function getErrorList() + /** + * @param string $testFile + * @return int[] + */ + public function getErrorList($testFile = '') { return []; } - public function getWarningList() + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') { return [ 6 => 1, diff --git a/test/Sniffs/Namespaces/UseDoesNotStartWithBackslashUnitTest.php b/test/Sniffs/Namespaces/UseDoesNotStartWithBackslashUnitTest.php index ed2c3a22..c86f6512 100644 --- a/test/Sniffs/Namespaces/UseDoesNotStartWithBackslashUnitTest.php +++ b/test/Sniffs/Namespaces/UseDoesNotStartWithBackslashUnitTest.php @@ -5,6 +5,10 @@ class UseDoesNotStartWithBackslashUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -14,6 +18,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/NamingConventions/ValidVariableNameUnitTest.php b/test/Sniffs/NamingConventions/ValidVariableNameUnitTest.php index 91ff687b..e15f2040 100644 --- a/test/Sniffs/NamingConventions/ValidVariableNameUnitTest.php +++ b/test/Sniffs/NamingConventions/ValidVariableNameUnitTest.php @@ -5,6 +5,10 @@ class ValidVariableNameUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -14,6 +18,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Operators/BooleanOperatorUnitTest.php b/test/Sniffs/Operators/BooleanOperatorUnitTest.php index 1c7d4480..65bc07f9 100644 --- a/test/Sniffs/Operators/BooleanOperatorUnitTest.php +++ b/test/Sniffs/Operators/BooleanOperatorUnitTest.php @@ -5,6 +5,10 @@ class BooleanOperatorUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -19,6 +23,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Operators/TernaryOperatorUnitTest.php b/test/Sniffs/Operators/TernaryOperatorUnitTest.php index 98e7498d..0334ed3a 100644 --- a/test/Sniffs/Operators/TernaryOperatorUnitTest.php +++ b/test/Sniffs/Operators/TernaryOperatorUnitTest.php @@ -5,6 +5,10 @@ class TernaryOperatorUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -21,6 +25,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php index 7aa28ebe..d196283b 100644 --- a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php +++ b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php @@ -5,6 +5,10 @@ class CorrectClassNameCaseUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { switch ($testFile) { @@ -53,6 +57,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/PHP/ImportInternalConstantUnitTest.php b/test/Sniffs/PHP/ImportInternalConstantUnitTest.php index cda3406c..426ef218 100644 --- a/test/Sniffs/PHP/ImportInternalConstantUnitTest.php +++ b/test/Sniffs/PHP/ImportInternalConstantUnitTest.php @@ -5,6 +5,10 @@ class ImportInternalConstantUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { switch ($testFile) { @@ -32,6 +36,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/PHP/ImportInternalFunctionUnitTest.php b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.php index f99ebb4b..f326c12c 100644 --- a/test/Sniffs/PHP/ImportInternalFunctionUnitTest.php +++ b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.php @@ -5,6 +5,10 @@ class ImportInternalFunctionUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { switch ($testFile) { @@ -45,6 +49,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.php b/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.php index 0261d88d..676a1e1e 100644 --- a/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.php +++ b/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.php @@ -5,6 +5,10 @@ class InstantiatingParenthesisUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -24,6 +28,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/PHP/LowerCaseKeywordUnitTest.php b/test/Sniffs/PHP/LowerCaseKeywordUnitTest.php index 22e76c67..89fefe80 100644 --- a/test/Sniffs/PHP/LowerCaseKeywordUnitTest.php +++ b/test/Sniffs/PHP/LowerCaseKeywordUnitTest.php @@ -5,6 +5,10 @@ class LowerCaseKeywordUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -51,6 +55,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/PHP/RedundantSemicolonUnitTest.php b/test/Sniffs/PHP/RedundantSemicolonUnitTest.php index 9ae3165d..3ebb366e 100644 --- a/test/Sniffs/PHP/RedundantSemicolonUnitTest.php +++ b/test/Sniffs/PHP/RedundantSemicolonUnitTest.php @@ -5,6 +5,10 @@ class RedundantSemicolonUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -15,6 +19,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/PHP/TypeCastingUnitTest.php b/test/Sniffs/PHP/TypeCastingUnitTest.php index 40b67698..b8a7afd3 100644 --- a/test/Sniffs/PHP/TypeCastingUnitTest.php +++ b/test/Sniffs/PHP/TypeCastingUnitTest.php @@ -5,6 +5,10 @@ class TypeCastingUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -40,6 +44,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/Strings/NoConcatenationAtTheEndUnitTest.php b/test/Sniffs/Strings/NoConcatenationAtTheEndUnitTest.php index 63324c15..8d68b770 100644 --- a/test/Sniffs/Strings/NoConcatenationAtTheEndUnitTest.php +++ b/test/Sniffs/Strings/NoConcatenationAtTheEndUnitTest.php @@ -5,6 +5,10 @@ class NoConcatenationAtTheEndUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -13,6 +17,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/TestCase.php b/test/Sniffs/TestCase.php index f6996bbe..97a71228 100644 --- a/test/Sniffs/TestCase.php +++ b/test/Sniffs/TestCase.php @@ -87,7 +87,7 @@ protected function getTestFiles($testFileBase) /** * Should this test be skipped for some reason. * - * @return bool + * @return false */ protected function shouldSkipTest() { @@ -96,8 +96,6 @@ protected function shouldSkipTest() /** * Tests the extending classes Sniff class. - * - * @return void */ final public function testSniff() { @@ -178,7 +176,7 @@ final public function testSniff() * Generate a list of test failures for a given sniffed file. * * @param LocalFile $file The file being tested. - * @return array + * @return string[] * @throws RuntimeException */ public function generateFailureMessages(LocalFile $file) @@ -364,7 +362,7 @@ public function generateFailureMessages(LocalFile $file) * * @param string $filename The name of the file being tested. * @param Config $config The config data for the run. - * @return array + * @return string[] */ public function setCliValues($filename, Config $config) { @@ -377,7 +375,7 @@ public function setCliValues($filename, Config $config) * 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(int => int) + * @return int[] */ abstract protected function getErrorList(); @@ -387,7 +385,7 @@ abstract protected function getErrorList(); * 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(int => int) + * @return int[] */ abstract protected function getWarningList(); } diff --git a/test/Sniffs/WhiteSpace/BlankLineUnitTest.php b/test/Sniffs/WhiteSpace/BlankLineUnitTest.php index 7a34b27c..bb26a55e 100644 --- a/test/Sniffs/WhiteSpace/BlankLineUnitTest.php +++ b/test/Sniffs/WhiteSpace/BlankLineUnitTest.php @@ -5,6 +5,10 @@ class BlankLineUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -17,6 +21,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.php b/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.php index cc5e2e90..ee0564d1 100644 --- a/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.php +++ b/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.php @@ -5,6 +5,10 @@ class CommaSpacingUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -26,6 +30,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/WhiteSpace/NoBlankLineAtStartUnitTest.php b/test/Sniffs/WhiteSpace/NoBlankLineAtStartUnitTest.php index 1cd2a912..1b219789 100644 --- a/test/Sniffs/WhiteSpace/NoBlankLineAtStartUnitTest.php +++ b/test/Sniffs/WhiteSpace/NoBlankLineAtStartUnitTest.php @@ -5,6 +5,10 @@ class NoBlankLineAtStartUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { return [ @@ -21,6 +25,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php index 490713a0..54b99710 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php @@ -5,6 +5,10 @@ class ScopeIndentUnitTest extends TestCase { + /** + * @param string $testFile + * @return int[] + */ public function getErrorList($testFile = '') { if ($testFile === 'ScopeIndentUnitTest.1.inc') { @@ -234,6 +238,10 @@ public function getErrorList($testFile = '') ]; } + /** + * @param string $testFile + * @return int[] + */ public function getWarningList($testFile = '') { return []; From 27b724f0562eb8f5ef827487463c4146f4f8d4fe Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 18:46:44 +0100 Subject: [PATCH 146/225] Added Commenting DataProviderTag sniff Previously these checks were in FunctionCommentSniff. - `@dataProvider` tag is allowed only on test* methods - data provider can name can't have `Provider` suffix - checks if data provider name is given with the tag - checks if method accepts some params --- .../FunctionDataProviderTagSniff.php | 87 +++++++++++++++++++ .../FunctionDataProviderTagUnitTest.inc | 37 ++++++++ .../FunctionDataProviderTagUnitTest.php | 30 +++++++ 3 files changed, 154 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/Commenting/FunctionDataProviderTagSniff.php create mode 100644 test/Sniffs/Commenting/FunctionDataProviderTagUnitTest.inc create mode 100644 test/Sniffs/Commenting/FunctionDataProviderTagUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionDataProviderTagSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionDataProviderTagSniff.php new file mode 100644 index 00000000..5a00118f --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionDataProviderTagSniff.php @@ -0,0 +1,87 @@ +getTokens(); + $skip = Tokens::$methodPrefixes + + [T_WHITESPACE => T_WHITESPACE]; + + $commentEnd = $phpcsFile->findPrevious($skip, $stackPtr - 1, null, true); + // There is no doc-comment for the function. + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG) { + return; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + $tags = $tokens[$commentStart]['comment_tags']; + + // Checks @dataProvider tags + foreach ($tags as $pos => $tag) { + if (strtolower($tokens[$tag]['content']) !== '@dataprovider') { + continue; + } + + // Check if method name starts from "test". + $functionPtr = $phpcsFile->findNext(T_FUNCTION, $tag + 1); + $namePtr = $phpcsFile->findNext(T_STRING, $functionPtr + 1); + $functionName = $tokens[$namePtr]['content']; + + if (strpos($functionName, 'test') !== 0) { + $error = 'Tag @dataProvider is allowed only for test* methods.'; + $phpcsFile->addError($error, $tag, 'NoTestMethod'); + return; + } + + $params = $phpcsFile->getMethodParameters($functionPtr); + if (! $params) { + $error = 'Function "%s" does not accept any parameters.'; + $data = [$functionName]; + $phpcsFile->addError($error, $namePtr, 'MissingParameters', $data); + } + + // Check if data provider name is given and does not have "Provider" suffix. + if ($tokens[$tag + 1]['code'] !== T_DOC_COMMENT_WHITESPACE + || $tokens[$tag + 2]['code'] !== T_DOC_COMMENT_STRING + ) { + $error = 'Missing data provider name.'; + $phpcsFile->addError($error, $tag, 'MissingName'); + } else { + $providerName = $tokens[$tag + 2]['content']; + + if (preg_match('/Provider$/', $providerName)) { + $error = 'Data provider name should have "Provider" suffix.'; + $phpcsFile->addError($error, $tag, 'DataProviderInvalidName'); + } + } + } + } +} diff --git a/test/Sniffs/Commenting/FunctionDataProviderTagUnitTest.inc b/test/Sniffs/Commenting/FunctionDataProviderTagUnitTest.inc new file mode 100644 index 00000000..2ff0e4eb --- /dev/null +++ b/test/Sniffs/Commenting/FunctionDataProviderTagUnitTest.inc @@ -0,0 +1,37 @@ + 1, + 16 => 1, + 19 => 1, + 25 => 1, + ]; + } + + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') + { + return []; + } +} From 4e9465ce9a2e1e3cf96c5f6cab85af9dced0cce1 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 18:49:17 +0100 Subject: [PATCH 147/225] Added new sniff - Commenting NoInlineCommentAfterCurlyClose --- .../NoInlineCommentAfterCurlyCloseSniff.php | 44 +++++++++++++++++++ ...NoInlineCommentAfterCurlyCloseUnitTest.inc | 28 ++++++++++++ ...NoInlineCommentAfterCurlyCloseUnitTest.php | 30 +++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseSniff.php create mode 100644 test/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseUnitTest.inc create mode 100644 test/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseSniff.php new file mode 100644 index 00000000..094093be --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseSniff.php @@ -0,0 +1,44 @@ +getTokens(); + + $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); + if (! $next) { + return; + } + + if ($tokens[$next]['code'] !== T_COMMENT) { + return; + } + + if ($tokens[$next]['line'] > $tokens[$stackPtr]['line']) { + return; + } + + $error = 'Inline comment is not allowed after closing curly bracket.'; + $phpcsFile->addError($error, $next, 'NotAllowed'); + } +} diff --git a/test/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseUnitTest.inc b/test/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseUnitTest.inc new file mode 100644 index 00000000..4519fa8c --- /dev/null +++ b/test/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseUnitTest.inc @@ -0,0 +1,28 @@ + 0) { + if ($a) { + --$a; + } // end if + } // end while + } // end __construct + + public function method($a) + { + switch ($a) { + case 1: + if ($a > 1) { + ++$a; + } + // no break + case 2: + default: + } // end switch + + return $a; + } +} \ No newline at end of file diff --git a/test/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseUnitTest.php b/test/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseUnitTest.php new file mode 100644 index 00000000..fa6f827f --- /dev/null +++ b/test/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseUnitTest.php @@ -0,0 +1,30 @@ + 1, + 11 => 1, + 12 => 1, + 24 => 1, + ]; + } + + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') + { + return []; + } +} From 601ede75694590cdea5ba72d060d1970a41b5dbe Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 18:52:22 +0100 Subject: [PATCH 148/225] Added new sniff - Commenting TagCase Added PHPDocs tags and PHPUnit annotations. --- .../Sniffs/Commenting/TagCaseSniff.php | 117 ++++++++++++++++++ test/Sniffs/Commenting/TagCaseUnitTest.inc | 75 +++++++++++ .../Commenting/TagCaseUnitTest.inc.fixed | 75 +++++++++++ test/Sniffs/Commenting/TagCaseUnitTest.php | 86 +++++++++++++ 4 files changed, 353 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/Commenting/TagCaseSniff.php create mode 100644 test/Sniffs/Commenting/TagCaseUnitTest.inc create mode 100644 test/Sniffs/Commenting/TagCaseUnitTest.inc.fixed create mode 100644 test/Sniffs/Commenting/TagCaseUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Commenting/TagCaseSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/TagCaseSniff.php new file mode 100644 index 00000000..92728519 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Commenting/TagCaseSniff.php @@ -0,0 +1,117 @@ + '@api', + '@author' => '@author', + '@category' => '@category', + '@copyright' => '@copyright', + '@deprecated' => '@deprecated', + '@example' => '@example', + '@filesource' => '@filesource', + '@global' => '@global', + '@ignore' => '@ignore', + '@inheritdoc' => '@inheritDoc', + '@internal' => '@internal', + '@license' => '@license', + '@link' => '@link', + '@method' => '@method', + '@package' => '@package', + '@param' => '@param', + '@property' => '@property', + '@property-read' => '@property-read', + '@property-write' => '@property-write', + '@return' => '@return', + '@see' => '@see', + '@since' => '@since', + '@source' => '@source', + '@subpackage' => '@subpackage', + '@throws' => '@throws', + '@todo' => '@todo', + '@uses' => '@uses', + '@used-by' => '@used-by', + '@var' => '@var', + '@version' => '@version', + // PHPUnit annotations + '@after' => '@after', + '@afterclass' => '@afterClass', + '@backupglobals' => '@backupGlobals', + '@backupstaticattributes' => '@backupStaticAttributes', + '@before' => '@before', + '@beforeclass' => '@beforeClass', + '@codecoverageignore' => '@codeCoverageIgnore', + '@codecoverageignorestart' => '@codeCoverageIgnoreStart', + '@codecoverageignoreend' => '@codeCoverageIgnoreEnd', + '@covers' => '@covers', + '@coversdefaultclass' => '@coversDefaultClass', + '@coversnothing' => '@coversNothing', + '@dataprovider' => '@dataProvider', + '@depends' => '@depends', + '@expectedexception' => '@expectedException', + '@expectedexceptioncode' => '@expectedExceptionCode', + '@expectedexceptionmessage' => '@expectedExceptionMessage', + '@expectedexceptionmessageregexp' => '@expectedExceptionMessageRegExp', + '@group' => '@group', + '@large' => '@large', + '@medium' => '@medium', + '@preserveglobalstate' => '@preserveGlobalState', + '@requires' => '@requires', + '@runtestsinseparateprocesses' => '@runTestsInSeparateProcesses', + '@runinseparateprocess' => '@runInSeparateProcess', + '@small' => '@small', + '@test' => '@test', + '@testdox' => '@testdox', + '@ticket' => '@ticket', + ]; + + /** + * @return int[] + */ + public function register() + { + return [T_DOC_COMMENT_TAG]; + } + + /** + * @param int $stackPtr + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $lower = strtolower($content); + if (! isset($this->tags[$lower])) { + return; + } + + if ($this->tags[$lower] === $content) { + return; + } + + $tagName = $this->tags[$lower]; + $error = 'Invalid case tag. Expected "%s", but found "%s"'; + $errorCode = sprintf('%sTagWrongCase', ucfirst($tagName)); + $data = [ + $tagName, + $content, + ]; + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } +} diff --git a/test/Sniffs/Commenting/TagCaseUnitTest.inc b/test/Sniffs/Commenting/TagCaseUnitTest.inc new file mode 100644 index 00000000..f4362085 --- /dev/null +++ b/test/Sniffs/Commenting/TagCaseUnitTest.inc @@ -0,0 +1,75 @@ + 1, + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 18 => 1, + 19 => 1, + 20 => 1, + 21 => 1, + 22 => 1, + 23 => 1, + 24 => 1, + 25 => 1, + 26 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 32 => 1, + 33 => 1, + // PHPUnit Annotations + 37 => 1, + 38 => 1, + 39 => 1, + 40 => 1, + 41 => 1, + 42 => 1, + 43 => 1, + 44 => 1, + 45 => 1, + 46 => 1, + 47 => 1, + 48 => 1, + 49 => 1, + 50 => 1, + 51 => 1, + 52 => 1, + 53 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 60 => 1, + 61 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + ]; + } + + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') + { + return []; + } +} From d49fc71d77f7528f894c14b40b5938f3e857e8a5 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 18:54:46 +0100 Subject: [PATCH 149/225] Added new sniff - Commenting FunctionDisallowedTag --- .../Commenting/FunctionDisallowedTagSniff.php | 93 +++++++++++++++++++ .../FunctionDisallowedTagUnitTest.inc | 53 +++++++++++ .../FunctionDisallowedTagUnitTest.php | 39 ++++++++ 3 files changed, 185 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/Commenting/FunctionDisallowedTagSniff.php create mode 100644 test/Sniffs/Commenting/FunctionDisallowedTagUnitTest.inc create mode 100644 test/Sniffs/Commenting/FunctionDisallowedTagUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionDisallowedTagSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionDisallowedTagSniff.php new file mode 100644 index 00000000..d255f5ac --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionDisallowedTagSniff.php @@ -0,0 +1,93 @@ + 'Information about the author will be found with the commit.', + '@copyright' => 'Please see copyright notes on the top of the file.', + '@license' => 'Please see license notes on the top of the file.', + '@package' => '', + '@subpackage' => '', + '@version' => '', + '@inheritDoc' => 'Please define explicitly params, return type and throws for the method.', + '@expectedException' => 'Please use appropriate method instead just before call' + . ' which should throw the exception.', + '@expectedExceptionCode' => 'Please use appropriate method instead just before call' + . ' which should throw the exception.', + '@expectedExceptionMessage' => 'Please use appropriate method instead just before call' + . ' which should throw the exception.', + '@expectedExceptionMessageRegExp' => 'Please use appropriate method instead just before call' + . ' which should throw the exception.', + ]; + + /** + * @return int[] + */ + public function register() + { + return [T_FUNCTION]; + } + + /** + * @param int $stackPtr + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $skip = Tokens::$methodPrefixes + + [T_WHITESPACE => T_WHITESPACE]; + + $commentEnd = $phpcsFile->findPrevious($skip, $stackPtr - 1, null, true); + // There is no doc-comment for the function. + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG) { + return; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + $content = strtolower($tokens[$tag]['content']); + $result = array_filter($this->disallowedTags, function ($key) use ($content) { + return strtolower($key) === $content; + }, ARRAY_FILTER_USE_KEY); + + if (! $result) { + continue; + } + + $tagName = key($result); + $tagError = current($result); + $error = 'Tag %s is not allowed. %s'; + $errorCode = sprintf('%sTagNotAllowed', ucfirst(substr($tagName, 1))); + $data = [ + $tagName, + $tagError, + ]; + + $phpcsFile->addError($error, $tag, $errorCode, $data); + } + } +} diff --git a/test/Sniffs/Commenting/FunctionDisallowedTagUnitTest.inc b/test/Sniffs/Commenting/FunctionDisallowedTagUnitTest.inc new file mode 100644 index 00000000..6042a343 --- /dev/null +++ b/test/Sniffs/Commenting/FunctionDisallowedTagUnitTest.inc @@ -0,0 +1,53 @@ + 1, + 13 => 1, + 14 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 19 => 1, + 20 => 1, + 30 => 1, + 31 => 1, + 32 => 1, + 33 => 1, + 35 => 1, + ]; + } + + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') + { + return []; + } +} From 434c7d2cdb3ec2e60962d8d60d686ef1028b275f Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 19:49:37 +0100 Subject: [PATCH 150/225] Changed default number of spaces before colon to 1 in return type declaration --- src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php index ed147e62..299aa851 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php @@ -25,7 +25,7 @@ class ReturnTypeSniff implements Sniff /** * @var int */ - public $spacesBeforeColon = 0; + public $spacesBeforeColon = 1; /** * @var int From fa4c90fe40439f86d0604dfd2e4655182c09cd76 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 20:20:05 +0100 Subject: [PATCH 151/225] Allow parenthesis on nested coalesce operator in ternaty operator $a = $b ? ($c ?? 1) : $d; $a = $b ? $c : ($d ?? 1); --- .../Sniffs/Formatting/UnnecessaryParenthesesSniff.php | 1 + test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc | 3 +++ .../Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed | 3 +++ 3 files changed, 7 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php index 9cdde574..71703cba 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -227,6 +227,7 @@ public function process(File $phpcsFile, $stackPtr) Tokens::$assignmentTokens + Tokens::$booleanOperators + [ + T_COALESCE => T_COALESCE, T_INLINE_ELSE => T_INLINE_ELSE, T_INLINE_THEN => T_INLINE_THEN, ], diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc index 7041ae2f..7f167e0d 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc @@ -154,5 +154,8 @@ class UnnecessaryParentheses list($var) = explode(',', '1,2,3'); $date = (new DateTime())->modify('+1 year'); + + $a = $b ? ($c ?? 1) : 0; + $a = $b ? 0 : ($c ?? 1); } } diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed index 69fca663..e4dc77d7 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed @@ -154,5 +154,8 @@ class UnnecessaryParentheses list($var) = explode(',', '1,2,3'); $date = (new DateTime())->modify('+1 year'); + + $a = $b ? ($c ?? 1) : 0; + $a = $b ? 0 : ($c ?? 1); } } From ff5a7f40ae539f9b03686c127281410e8b9542b2 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 21:59:31 +0100 Subject: [PATCH 152/225] Removed PHP 5.6 compatibility checks mode in ruleset All sniffs now work teh same on PHP 5.6 and 7+ --- src/ZendCodingStandard/ruleset.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ZendCodingStandard/ruleset.xml b/src/ZendCodingStandard/ruleset.xml index 3901581c..f87381fb 100755 --- a/src/ZendCodingStandard/ruleset.xml +++ b/src/ZendCodingStandard/ruleset.xml @@ -6,9 +6,6 @@ - - - From c805c0f63ec8af25c625f41de1155af4b8820601 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 19 Sep 2017 22:02:08 +0100 Subject: [PATCH 153/225] `@param` tag is redundant for params with type hint and default null value --- .../Sniffs/Functions/ParamSniff.php | 99 ++++--------------- test/Sniffs/Functions/ParamUnitTest.inc | 4 +- test/Sniffs/Functions/ParamUnitTest.inc.fixed | 16 +-- test/Sniffs/Functions/ParamUnitTest.php | 5 +- 4 files changed, 27 insertions(+), 97 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php index 29ee83ef..112d1387 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php @@ -3,7 +3,6 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; -use PHP_CodeSniffer\Util\Tokens; use ZendCodingStandard\Helper\Methods; use function array_filter; @@ -26,7 +25,6 @@ use function ucfirst; use function usort; -use const T_DOC_COMMENT_CLOSE_TAG; use const T_DOC_COMMENT_STAR; use const T_DOC_COMMENT_STRING; use const T_DOC_COMMENT_WHITESPACE; @@ -34,7 +32,6 @@ use const T_NS_SEPARATOR; use const T_NULLABLE; use const T_STRING; -use const T_WHITESPACE; class ParamSniff implements Sniff { @@ -75,7 +72,7 @@ public function process(File $phpcsFile, $stackPtr) if ($commentStart = $this->getCommentStart($phpcsFile, $stackPtr)) { $this->processParamDoc($phpcsFile, $stackPtr, $commentStart); } - $this->processParamSpec($phpcsFile, $stackPtr); + $this->processParamSpec($phpcsFile); } /** @@ -163,7 +160,7 @@ private function processParamDoc(File $phpcsFile, $stackPtr, $commentStart) $description = isset($split[2]) ? $split[2] : null; $type = $split[0]; - $this->checkParam($phpcsFile, current($param), $stackPtr, $tag, $name, $type, $description); + $this->checkParam($phpcsFile, current($param), $tag, $name, $type, $description); } $last = current($this->processedParams); @@ -262,7 +259,6 @@ private function replaceParamTypeHint(File $phpcsFile, $varPtr, $newTypeHint) /** * @param string[] $param Real param function details. - * @param null|int $methodPtr Position of the method definition token. * @param null|int $tagPtr Position of the @param tag. * @param null|string $name Name of the param in the @param tag. * @param null|string $typeStr Type of the param in the @param tag. @@ -271,7 +267,6 @@ private function replaceParamTypeHint(File $phpcsFile, $varPtr, $newTypeHint) private function checkParam( File $phpcsFile, array $param, - $methodPtr = null, $tagPtr = null, $name = null, $typeStr = null, @@ -320,19 +315,6 @@ private function checkParam( $param['name'], ]; $phpcsFile->addError($error, $param['token'], $code, $data); - } elseif (isset($param['default']) - && strtolower($param['default']) === 'null' - && $typeHint[0] !== '?' - ) { - $error = 'Parameter %s needs specification in PHPDocs'; - $data = [ - $param['name'], - ]; - $fix = $phpcsFile->addFixableError($error, $param['token'], 'MissingSpecificationNUll', $data); - - if ($fix) { - $this->addParameter($phpcsFile, $methodPtr, $param['name'], 'null|' . $param['type_hint']); - } } return; @@ -590,14 +572,23 @@ private function checkParam( // Check if PHPDocs param is required if ($typeHint && ! in_array($lowerTypeHint, $this->needSpecificationTypes, true) - && $this->typesMatch($typeHint, $typeStr) && ! $description ) { - $error = 'Param tag is redundant'; - $fix = $phpcsFile->addFixableError($error, $tagPtr, 'RedundantParamDoc'); + $tmpTypeHint = $typeHint; + if (isset($param['default']) + && strtolower($param['default']) === 'null' + && $tmpTypeHint[0] !== '?' + ) { + $tmpTypeHint = '?' . $tmpTypeHint; + } - if ($fix) { - $this->removeTag($phpcsFile, $tagPtr); + if ($this->typesMatch($tmpTypeHint, $typeStr)) { + $error = 'Param tag is redundant'; + $fix = $phpcsFile->addFixableError($error, $tagPtr, 'RedundantParamDoc'); + + if ($fix) { + $this->removeTag($phpcsFile, $tagPtr); + } } } } @@ -621,68 +612,14 @@ private function isType($str) return (bool) preg_match('/^((?:\\\\?[a-z0-9]+)+(?:\[\])*)(\|(?:\\\\?[a-z0-9]+)+(?:\[\])*)*$/i', $str); } - /** - * @param int $stackPtr - */ - private function processParamSpec(File $phpcsFile, $stackPtr) + private function processParamSpec(File $phpcsFile) { foreach ($this->params as $k => $param) { if (in_array($k, $this->processedParams, true)) { continue; } - $this->checkParam($phpcsFile, $param, $stackPtr); + $this->checkParam($phpcsFile, $param); } } - - /** - * @param int $methodPtr - * @param string $name - * @param string $type - */ - private function addParameter(File $phpcsFile, $methodPtr, $name, $type) - { - $tokens = $phpcsFile->getTokens(); - - $skip = Tokens::$methodPrefixes - + [T_WHITESPACE => T_WHITESPACE]; - - $commentEnd = $phpcsFile->findPrevious($skip, $methodPtr - 1, null, true); - if ($tokens[$commentEnd]['code'] === T_DOC_COMMENT_CLOSE_TAG) { - $firstOnLine = $phpcsFile->findFirstOnLine([], $commentEnd, true); - $indent = ' '; - $content = '* @param %3$s %4$s%2$s%1$s'; - if ($tokens[$firstOnLine]['code'] === T_DOC_COMMENT_WHITESPACE) { - $indent = $tokens[$firstOnLine]['content']; - } elseif ($tokens[$firstOnLine]['code'] === T_WHITESPACE) { - $indent .= $tokens[$firstOnLine]['content']; - $content = '%2$s%1$s* @param %3$s %4$s%2$s%1$s'; - } - - $before = $commentEnd; - } else { - $next = $phpcsFile->findNext(T_WHITESPACE, $commentEnd + 1, null, true); - $firstOnLine = $phpcsFile->findFirstOnLine([], $next, true); - $indent = ''; - if ($tokens[$firstOnLine]['code'] === T_WHITESPACE) { - $indent = $tokens[$firstOnLine]['content']; - } - - $content = '%1$s/**%2$s' - . '%1$s * @param %3$s %4$s%2$s' - . '%1$s */%2$s'; - - $before = $firstOnLine; - } - - $content = sprintf( - $content, - $indent, - $phpcsFile->eolChar, - $type, - $name - ); - - $phpcsFile->fixer->addContentBefore($before, $content); - } } diff --git a/test/Sniffs/Functions/ParamUnitTest.inc b/test/Sniffs/Functions/ParamUnitTest.inc index 6d4f9f4c..39de477a 100644 --- a/test/Sniffs/Functions/ParamUnitTest.inc +++ b/test/Sniffs/Functions/ParamUnitTest.inc @@ -287,10 +287,10 @@ class FunctionParam extends FunctionParamParent */ public function wrongParamOrder($a, DateTime $b, $c, $d) {} - public function paramNeedsTag1(string $a = null) {} + public function paramDoesNotNeedTag1(string $a = null) {} /** */ - public function paramNeedsTag2(int $int = null) {} + public function paramDoesNotNeedTag2(int $int = null) {} /** * @param null|int $a diff --git a/test/Sniffs/Functions/ParamUnitTest.inc.fixed b/test/Sniffs/Functions/ParamUnitTest.inc.fixed index 4aa4e280..77af1cba 100644 --- a/test/Sniffs/Functions/ParamUnitTest.inc.fixed +++ b/test/Sniffs/Functions/ParamUnitTest.inc.fixed @@ -253,9 +253,8 @@ class FunctionParam extends FunctionParamParent * @param null|DateTime|Something $b * @param string|DateTime|Something $c * - * @param null|DateTime $e - * @param null|string $f - * @param null|string $g + * + * */ public function defaultValueAndNull( $a, @@ -288,15 +287,10 @@ class FunctionParam extends FunctionParamParent */ public function wrongParamOrder($a, DateTime $b, $c, $d) {} - /** - * @param null|string $a - */ - public function paramNeedsTag1(string $a = null) {} + public function paramDoesNotNeedTag1(string $a = null) {} - /** - * @param null|int $int - */ - public function paramNeedsTag2(int $int = null) {} + /** */ + public function paramDoesNotNeedTag2(int $int = null) {} /** * @param null|int $a diff --git a/test/Sniffs/Functions/ParamUnitTest.php b/test/Sniffs/Functions/ParamUnitTest.php index 569a79f7..847340be 100644 --- a/test/Sniffs/Functions/ParamUnitTest.php +++ b/test/Sniffs/Functions/ParamUnitTest.php @@ -87,13 +87,12 @@ public function getErrorList($testFile = '') 252 => 1, 254 => 1, 255 => 1, - 265 => 1, + 256 => 1, + 257 => 1, 271 => 1, 272 => 1, 273 => 1, 282 => 1, - 290 => 1, - 293 => 1, 296 => 1, 301 => 1, ]; From be67318dd153b7e03b8598c50c7e12653c6be20e Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 20 Sep 2017 08:26:07 +0100 Subject: [PATCH 154/225] Updated to PHP_CodeSniffer 3.1.0 and fixed failing sniff Previously comment /**@someting*/ (without space after comment opening tag) was not recognized correctly as doc comment. It is fixed in 3.1.0. --- composer.json | 2 +- composer.lock | 50 +++++++++---------- .../Sniffs/Commenting/DocCommentSniff.php | 3 -- .../Commenting/DocCommentUnitTest.6.inc | 4 +- .../Commenting/DocCommentUnitTest.6.inc.fixed | 4 +- test/Sniffs/Commenting/DocCommentUnitTest.php | 2 +- 6 files changed, 31 insertions(+), 34 deletions(-) diff --git a/composer.json b/composer.json index 47502b38..6472d8da 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "coding standard" ], "require": { - "squizlabs/php_codesniffer": "3.0.2" + "squizlabs/php_codesniffer": "3.1.0" }, "require-dev": { "phpunit/phpunit": "^5.7.21 || ^6.3" diff --git a/composer.lock b/composer.lock index 31967b48..0cb3e87b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "3454fdc26d9443a15d82663c4b87ba66", + "content-hash": "401441888f37ac531215c21cf6c71533", "packages": [ { "name": "squizlabs/php_codesniffer", - "version": "3.0.2", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "c7594a88ae75401e8f8d0bd4deb8431b39045c51" + "reference": "3c2d0a0fe39684ba0c1eb842a6a775d0b938d699" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/c7594a88ae75401e8f8d0bd4deb8431b39045c51", - "reference": "c7594a88ae75401e8f8d0bd4deb8431b39045c51", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/3c2d0a0fe39684ba0c1eb842a6a775d0b938d699", + "reference": "3c2d0a0fe39684ba0c1eb842a6a775d0b938d699", "shasum": "" }, "require": { @@ -27,7 +27,7 @@ "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0" }, "bin": [ "bin/phpcs", @@ -55,7 +55,7 @@ "phpcs", "standards" ], - "time": "2017-07-18T01:12:32+00:00" + "time": "2017-09-19T22:47:14+00:00" } ], "packages-dev": [ @@ -157,16 +157,16 @@ }, { "name": "phpdocumentor/reflection-common", - "version": "1.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", "shasum": "" }, "require": { @@ -207,7 +207,7 @@ "reflection", "static analysis" ], - "time": "2015-12-27T11:43:31+00:00" + "time": "2017-09-11T18:02:19+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -303,22 +303,22 @@ }, { "name": "phpspec/prophecy", - "version": "v1.7.0", + "version": "v1.7.2", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" + "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6", + "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", "sebastian/comparator": "^1.1|^2.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, @@ -329,7 +329,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { @@ -362,7 +362,7 @@ "spy", "stub" ], - "time": "2017-03-02T20:05:34+00:00" + "time": "2017-09-04T11:05:03+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1269,20 +1269,20 @@ }, { "name": "symfony/yaml", - "version": "v3.3.6", + "version": "v3.3.9", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed" + "reference": "1d8c2a99c80862bdc3af94c1781bf70f86bccac0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/ddc23324e6cfe066f3dd34a37ff494fa80b617ed", - "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed", + "url": "https://api.github.com/repos/symfony/yaml/zipball/1d8c2a99c80862bdc3af94c1781bf70f86bccac0", + "reference": "1d8c2a99c80862bdc3af94c1781bf70f86bccac0", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "require-dev": { "symfony/console": "~2.8|~3.0" @@ -1320,7 +1320,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-07-23T12:43:26+00:00" + "time": "2017-07-29T21:54:42+00:00" }, { "name": "webmozart/assert", diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index d078b85a..c0053243 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -344,9 +344,6 @@ private function checkSpacesInOneLineComment(File $phpcsFile, $commentStart, $co $phpcsFile->fixer->replaceToken($commentStart + 1, ' '); } } elseif ($tokens[$commentStart + 1]['code'] !== T_DOC_COMMENT_WHITESPACE) { - // This case is currently not supported. - // Comment /**@var null $name; */ is not recognized as doc-block comment. - // todo: fix is already merged to PHP_CodeSniffer 3.1.0, need to be changed after release 3.1.0 $error = 'Expected 1 space after opening tag of one line doc block comment.'; $fix = $phpcsFile->addFixableError($error, $commentStart, 'InvalidSpacing'); diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.6.inc b/test/Sniffs/Commenting/DocCommentUnitTest.6.inc index ffe8bda8..da804673 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.6.inc +++ b/test/Sniffs/Commenting/DocCommentUnitTest.6.inc @@ -17,7 +17,7 @@ class OneLine /** @var null $no*/ $no = null; - /**@var null $notYetSupported*/ - $notYetSupported = null; + /**@var null $missingSpaces*/ + $missingSpaces = null; } } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.6.inc.fixed b/test/Sniffs/Commenting/DocCommentUnitTest.6.inc.fixed index 05f69f1e..92d97806 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.6.inc.fixed +++ b/test/Sniffs/Commenting/DocCommentUnitTest.6.inc.fixed @@ -17,7 +17,7 @@ class OneLine /** @var null $no */ $no = null; - /**@var null $notYetSupported*/ - $notYetSupported = null; + /** @var null $missingSpaces */ + $missingSpaces = null; } } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.php b/test/Sniffs/Commenting/DocCommentUnitTest.php index 770e8c29..d5c225c8 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.php +++ b/test/Sniffs/Commenting/DocCommentUnitTest.php @@ -69,7 +69,7 @@ public function getErrorList($testFile = '') 11 => 1, 14 => 2, 17 => 1, - // 20 => 2, // not yet supported + 20 => 2, ]; case 'DocCommentUnitTest.7.inc': return [ From b5bf03841faa588e3f7f2f1ba05971f735b8d67d Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 20 Sep 2017 09:18:22 +0100 Subject: [PATCH 155/225] Fixed detecting thrown exception in methods --- .../Sniffs/Functions/ThrowsSniff.php | 13 ++++++------- test/Sniffs/Functions/ThrowsUnitTest.inc | 5 +++++ test/Sniffs/Functions/ThrowsUnitTest.php | 3 ++- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php index 72a67326..e7311f64 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php @@ -170,10 +170,7 @@ protected function processThrowStatements(File $phpcsFile, $stackPtr) } $thrownExceptions[] = $suggested; - } else { - // the next token is not a valid name - it could be variable name - $error = 'Expected exception class name'; - $phpcsFile->addError($error, $currException, 'ThrowClassName'); + continue; } } elseif ($tokens[$next]['code'] === T_VARIABLE) { $catch = $phpcsFile->findPrevious(T_CATCH, $throw, $scopeBegin); @@ -196,10 +193,12 @@ protected function processThrowStatements(File $phpcsFile, $stackPtr) $thrownExceptions[] = $exception; } } - } else { - ++$thrownVariables; + + continue; } } + + ++$thrownVariables; } if (! $foundThrows) { @@ -216,7 +215,7 @@ protected function processThrowStatements(File $phpcsFile, $stackPtr) $thrownExceptions = array_unique($thrownExceptions); // Make sure @throws tag count matches thrown count. - $thrownCount = count($thrownExceptions); + $thrownCount = count($thrownExceptions) ?: 1; $tagCount = count(array_unique($this->throwTags)); if ($thrownVariables > 0) { diff --git a/test/Sniffs/Functions/ThrowsUnitTest.inc b/test/Sniffs/Functions/ThrowsUnitTest.inc index 3a1ba760..ae1b265c 100644 --- a/test/Sniffs/Functions/ThrowsUnitTest.inc +++ b/test/Sniffs/Functions/ThrowsUnitTest.inc @@ -181,6 +181,11 @@ class ThrowUnitTest { } + public function throwExceptionFromFactory() + { + throw ExceptionFacotry::create(); + } + public function throwVariableAndException() { $e = new Exception(); diff --git a/test/Sniffs/Functions/ThrowsUnitTest.php b/test/Sniffs/Functions/ThrowsUnitTest.php index 0c8566b2..4ffdd5e7 100644 --- a/test/Sniffs/Functions/ThrowsUnitTest.php +++ b/test/Sniffs/Functions/ThrowsUnitTest.php @@ -25,9 +25,10 @@ public function getErrorList($testFile = '') 127 => 1, 142 => 1, 160 => 1, - 174 => 1, + 171 => 1, 178 => 1, 184 => 1, + 189 => 1, ]; } From 0a4b63a0da602e66678278885219b262977731a8 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 17 Oct 2017 22:49:01 +0100 Subject: [PATCH 156/225] Updated Travis CI configuration Run build on PHP 7.2 and fixed legacy dependencies --- .travis.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 38e987cc..8f786309 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,6 @@ env: global: - COMPOSER_ARGS="--no-interaction" - COVERAGE_DEPS="satooshi/php-coveralls" - - LEGACY_DEPS="phpunit/phpunit" matrix: include: @@ -21,7 +20,7 @@ matrix: - php: 5.6 env: - DEPS=locked - - TEST_COVERAGE=true + - LEGACY_DEPS="phpunit/phpunit" - php: 5.6 env: - DEPS=latest @@ -31,7 +30,9 @@ matrix: - php: 7 env: - DEPS=locked + - LEGACY_DEPS="doctrine/instantiator" - CS_CHECK=true + - TEST_COVERAGE=true - php: 7 env: - DEPS=latest @@ -44,17 +45,17 @@ matrix: - php: 7.1 env: - DEPS=latest - - php: nightly + - php: 7.2 env: - DEPS=lowest - - php: nightly + - php: 7.2 env: - DEPS=locked - - php: nightly + - php: 7.2 env: - DEPS=latest allow_failures: - - php: nightly + - php: 7.2 before_install: - if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi @@ -62,12 +63,11 @@ before_install: install: - travis_retry composer install $COMPOSER_ARGS --ignore-platform-reqs - - if [[ $TRAVIS_PHP_VERSION =~ ^5.6 ]]; then travis_retry composer update $COMPOSER_ARGS --with-dependencies $LEGACY_DEPS ; fi + - if [[ $LEGACY_DEPS != '' ]]; then travis_retry composer update $COMPOSER_ARGS --with-dependencies $LEGACY_DEPS ; fi - if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi - - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update $COMPOSER_ARGS --prefer-lowest --prefer-stable ; fi + - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-lowest --prefer-stable $COMPOSER_ARGS ; fi - if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $COVERAGE_DEPS ; fi - - stty cols 120 - - COLUMNS=120 composer show + - stty cols 120 && composer show script: - if [[ $TEST_COVERAGE == 'true' ]]; then composer test-coverage ; else composer test ; fi From 08249aa91ed31f069e4f3153df36117833537048 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 17 Oct 2017 22:49:40 +0100 Subject: [PATCH 157/225] Updated dependencies - PHP_CodeSniffer 3.1.1 --- composer.json | 4 +- composer.lock | 498 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 319 insertions(+), 183 deletions(-) diff --git a/composer.json b/composer.json index 6472d8da..35e21927 100644 --- a/composer.json +++ b/composer.json @@ -7,10 +7,10 @@ "coding standard" ], "require": { - "squizlabs/php_codesniffer": "3.1.0" + "squizlabs/php_codesniffer": "3.1.1" }, "require-dev": { - "phpunit/phpunit": "^5.7.21 || ^6.3" + "phpunit/phpunit": "^5.7.23 || ^6.4.3" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 0cb3e87b..ab32ef7c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "401441888f37ac531215c21cf6c71533", + "content-hash": "f1caeffc0e3157c2e667237a883b28a3", "packages": [ { "name": "squizlabs/php_codesniffer", - "version": "3.1.0", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "3c2d0a0fe39684ba0c1eb842a6a775d0b938d699" + "reference": "d667e245d5dcd4d7bf80f26f2c947d476b66213e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/3c2d0a0fe39684ba0c1eb842a6a775d0b938d699", - "reference": "3c2d0a0fe39684ba0c1eb842a6a775d0b938d699", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d667e245d5dcd4d7bf80f26f2c947d476b66213e", + "reference": "d667e245d5dcd4d7bf80f26f2c947d476b66213e", "shasum": "" }, "require": { @@ -55,38 +55,38 @@ "phpcs", "standards" ], - "time": "2017-09-19T22:47:14+00:00" + "time": "2017-10-16T22:40:25+00:00" } ], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": "^7.1" }, "require-dev": { "athletic/athletic": "~0.1.8", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "phpunit/phpunit": "^6.2.3", + "squizlabs/php_codesniffer": "^3.0.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -111,7 +111,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14T21:17:01+00:00" + "time": "2017-07-22T11:58:36+00:00" }, { "name": "myclabs/deep-copy", @@ -155,6 +155,108 @@ ], "time": "2017-04-12T18:52:22+00:00" }, + { + "name": "phar-io/manifest", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^1.0.1", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2017-03-05T18:14:27+00:00" + }, + { + "name": "phar-io/version", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2017-03-05T17:38:23+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "1.0.1", @@ -211,22 +313,22 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "3.2.2", + "version": "4.1.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157" + "reference": "2d3d238c433cf69caeb4842e97a3223a116f94b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/4aada1f93c72c35e22fb1383b47fee43b8f1d157", - "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/2d3d238c433cf69caeb4842e97a3223a116f94b2", + "reference": "2d3d238c433cf69caeb4842e97a3223a116f94b2", "shasum": "" }, "require": { - "php": ">=5.5", + "php": "^7.0", "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.3.0", + "phpdocumentor/type-resolver": "^0.4.0", "webmozart/assert": "^1.0" }, "require-dev": { @@ -252,20 +354,20 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-08-08T06:39:58+00:00" + "time": "2017-08-30T18:51:59+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.3.0", + "version": "0.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773" + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fb3933512008d8162b3cdf9e18dba9309b7c3773", - "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", "shasum": "" }, "require": { @@ -299,7 +401,7 @@ "email": "me@mikevanriel.com" } ], - "time": "2017-06-03T08:32:36+00:00" + "time": "2017-07-14T14:27:02+00:00" }, { "name": "phpspec/prophecy", @@ -366,40 +468,41 @@ }, { "name": "phpunit/php-code-coverage", - "version": "4.0.8", + "version": "5.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" + "reference": "8ed1902a57849e117b5651fc1a5c48110946c06b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/8ed1902a57849e117b5651fc1a5c48110946c06b", + "reference": "8ed1902a57849e117b5651fc1a5c48110946c06b", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", - "php": "^5.6 || ^7.0", - "phpunit/php-file-iterator": "^1.3", - "phpunit/php-text-template": "^1.2", - "phpunit/php-token-stream": "^1.4.2 || ^2.0", - "sebastian/code-unit-reverse-lookup": "^1.0", - "sebastian/environment": "^1.3.2 || ^2.0", - "sebastian/version": "^1.0 || ^2.0" + "php": "^7.0", + "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^1.4.11 || ^2.0", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.0", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" }, "require-dev": { - "ext-xdebug": "^2.1.4", - "phpunit/phpunit": "^5.7" + "ext-xdebug": "^2.5", + "phpunit/phpunit": "^6.0" }, "suggest": { - "ext-xdebug": "^2.5.1" + "ext-xdebug": "^2.5.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "5.2.x-dev" } }, "autoload": { @@ -425,7 +528,7 @@ "testing", "xunit" ], - "time": "2017-04-02T07:44:40+00:00" + "time": "2017-08-03T12:40:43+00:00" }, { "name": "phpunit/php-file-iterator", @@ -566,29 +669,29 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.4.11", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" + "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9a02332089ac48e704c70f6cefed30c224e3c0b0", + "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^6.2.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -611,20 +714,20 @@ "keywords": [ "tokenizer" ], - "time": "2017-02-27T10:12:30+00:00" + "time": "2017-08-20T05:47:52+00:00" }, { "name": "phpunit/phpunit", - "version": "5.7.21", + "version": "6.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "3b91adfb64264ddec5a2dee9851f354aa66327db" + "reference": "06b28548fd2b4a20c3cd6e247dc86331a7d4db13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3b91adfb64264ddec5a2dee9851f354aa66327db", - "reference": "3b91adfb64264ddec5a2dee9851f354aa66327db", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/06b28548fd2b4a20c3cd6e247dc86331a7d4db13", + "reference": "06b28548fd2b4a20c3cd6e247dc86331a7d4db13", "shasum": "" }, "require": { @@ -633,33 +736,35 @@ "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "~1.3", - "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.6.2", - "phpunit/php-code-coverage": "^4.0.4", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "^1.2.4", - "sebastian/diff": "^1.4.3", - "sebastian/environment": "^1.3.4 || ^2.0", - "sebastian/exporter": "~2.0", - "sebastian/global-state": "^1.1", - "sebastian/object-enumerator": "~2.0", - "sebastian/resource-operations": "~1.0", - "sebastian/version": "~1.0.3|~2.0", - "symfony/yaml": "~2.1|~3.0" + "myclabs/deep-copy": "^1.6.1", + "phar-io/manifest": "^1.0.1", + "phar-io/version": "^1.0", + "php": "^7.0", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^5.2.2", + "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^1.0.9", + "phpunit/phpunit-mock-objects": "^4.0.3", + "sebastian/comparator": "^2.0.2", + "sebastian/diff": "^2.0", + "sebastian/environment": "^3.1", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^1.0", + "sebastian/version": "^2.0.1" }, "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2" + "phpdocumentor/reflection-docblock": "3.0.2", + "phpunit/dbunit": "<3.0" }, "require-dev": { "ext-pdo": "*" }, "suggest": { "ext-xdebug": "*", - "phpunit/php-invoker": "~1.1" + "phpunit/php-invoker": "^1.1" }, "bin": [ "phpunit" @@ -667,7 +772,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.7.x-dev" + "dev-master": "6.4.x-dev" } }, "autoload": { @@ -693,33 +798,33 @@ "testing", "xunit" ], - "time": "2017-06-21T08:11:54+00:00" + "time": "2017-10-16T13:18:59+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.4.4", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" + "reference": "2f789b59ab89669015ad984afa350c4ec577ade0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", - "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/2f789b59ab89669015ad984afa350c4ec577ade0", + "reference": "2f789b59ab89669015ad984afa350c4ec577ade0", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.6 || ^7.0", - "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2 || ^2.0" + "doctrine/instantiator": "^1.0.5", + "php": "^7.0", + "phpunit/php-text-template": "^1.2.1", + "sebastian/exporter": "^3.0" }, "conflict": { - "phpunit/phpunit": "<5.4.0" + "phpunit/phpunit": "<6.0" }, "require-dev": { - "phpunit/phpunit": "^5.4" + "phpunit/phpunit": "^6.0" }, "suggest": { "ext-soap": "*" @@ -727,7 +832,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2.x-dev" + "dev-master": "4.0.x-dev" } }, "autoload": { @@ -752,7 +857,7 @@ "mock", "xunit" ], - "time": "2017-06-30T09:13:00+00:00" + "time": "2017-08-03T14:08:16+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -801,30 +906,30 @@ }, { "name": "sebastian/comparator", - "version": "1.2.4", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + "reference": "ae068fede81d06e7bb9bb46a367210a3d3e1fe6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/ae068fede81d06e7bb9bb46a367210a3d3e1fe6a", + "reference": "ae068fede81d06e7bb9bb46a367210a3d3e1fe6a", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" + "php": "^7.0", + "sebastian/diff": "^2.0", + "sebastian/exporter": "^3.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -861,32 +966,32 @@ "compare", "equality" ], - "time": "2017-01-29T09:50:25+00:00" + "time": "2017-08-03T07:14:59+00:00" }, { "name": "sebastian/diff", - "version": "1.4.3", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^6.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -913,32 +1018,32 @@ "keywords": [ "diff" ], - "time": "2017-05-22T07:24:03+00:00" + "time": "2017-08-03T08:09:46+00:00" }, { "name": "sebastian/environment", - "version": "2.0.0", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "^5.0" + "phpunit/phpunit": "^6.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -963,34 +1068,34 @@ "environment", "hhvm" ], - "time": "2016-11-26T07:53:53+00:00" + "time": "2017-07-01T08:51:00+00:00" }, { "name": "sebastian/exporter", - "version": "2.0.0", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~2.0" + "php": "^7.0", + "sebastian/recursion-context": "^3.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -1030,27 +1135,27 @@ "export", "exporter" ], - "time": "2016-11-19T08:54:04+00:00" + "time": "2017-04-03T13:19:02+00:00" }, { "name": "sebastian/global-state", - "version": "1.1.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^6.0" }, "suggest": { "ext-uopz": "*" @@ -1058,7 +1163,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1081,33 +1186,34 @@ "keywords": [ "global state" ], - "time": "2015-10-12T03:26:01+00:00" + "time": "2017-04-27T15:39:26+00:00" }, { "name": "sebastian/object-enumerator", - "version": "2.0.1", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", "shasum": "" }, "require": { - "php": ">=5.6", - "sebastian/recursion-context": "~2.0" + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" }, "require-dev": { - "phpunit/phpunit": "~5" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -1127,32 +1233,77 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-02-18T15:18:39+00:00" + "time": "2017-08-03T12:35:26+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "773f97c67f28de00d397be301821b06708fca0be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", + "reference": "773f97c67f28de00d397be301821b06708fca0be", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2017-03-29T09:07:27+00:00" }, { "name": "sebastian/recursion-context", - "version": "2.0.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -1180,7 +1331,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-11-19T07:33:16+00:00" + "time": "2017-03-03T06:23:57+00:00" }, { "name": "sebastian/resource-operations", @@ -1268,59 +1419,44 @@ "time": "2016-10-03T07:35:21+00:00" }, { - "name": "symfony/yaml", - "version": "v3.3.9", + "name": "theseer/tokenizer", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "1d8c2a99c80862bdc3af94c1781bf70f86bccac0" + "url": "https://github.com/theseer/tokenizer.git", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/1d8c2a99c80862bdc3af94c1781bf70f86bccac0", - "reference": "1d8c2a99c80862bdc3af94c1781bf70f86bccac0", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" - }, - "require-dev": { - "symfony/console": "~2.8|~3.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.3-dev" - } - }, "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" } ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2017-07-29T21:54:42+00:00" + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2017-04-07T12:08:54+00:00" }, { "name": "webmozart/assert", From b1df502c337a1bd35852f34ab304d6e19cf8db2e Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 5 Dec 2017 23:13:04 +0000 Subject: [PATCH 158/225] Updated dependencies: PHP_CodeSniffer 3.2.2 --- composer.json | 5 +- composer.lock | 162 ++++++++++++++++++++++++++------------------------ 2 files changed, 88 insertions(+), 79 deletions(-) diff --git a/composer.json b/composer.json index 35e21927..4bcd40e8 100644 --- a/composer.json +++ b/composer.json @@ -4,13 +4,14 @@ "license": "BSD-3-Clause", "keywords": [ "zf", + "zendframework", "coding standard" ], "require": { - "squizlabs/php_codesniffer": "3.1.1" + "squizlabs/php_codesniffer": "3.2.2" }, "require-dev": { - "phpunit/phpunit": "^5.7.23 || ^6.4.3" + "phpunit/phpunit": "^5.7.26 || ^6.5.5" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index ab32ef7c..4b723a72 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "f1caeffc0e3157c2e667237a883b28a3", + "content-hash": "d5669c04b0f4337e5e2f0e6c06be4c5c", "packages": [ { "name": "squizlabs/php_codesniffer", - "version": "3.1.1", + "version": "3.2.2", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "d667e245d5dcd4d7bf80f26f2c947d476b66213e" + "reference": "d7c00c3000ac0ce79c96fcbfef86b49a71158cd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d667e245d5dcd4d7bf80f26f2c947d476b66213e", - "reference": "d667e245d5dcd4d7bf80f26f2c947d476b66213e", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d7c00c3000ac0ce79c96fcbfef86b49a71158cd1", + "reference": "d7c00c3000ac0ce79c96fcbfef86b49a71158cd1", "shasum": "" }, "require": { @@ -55,7 +55,7 @@ "phpcs", "standards" ], - "time": "2017-10-16T22:40:25+00:00" + "time": "2017-12-19T21:44:46+00:00" } ], "packages-dev": [ @@ -115,37 +115,40 @@ }, { "name": "myclabs/deep-copy", - "version": "1.6.1", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102" + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8e6e04167378abf1ddb4d3522d8755c5fd90d102", - "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": "^5.6 || ^7.0" }, "require-dev": { - "doctrine/collections": "1.*", - "phpunit/phpunit": "~4.1" + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^4.1" }, "type": "library", "autoload": { "psr-4": { "DeepCopy\\": "src/DeepCopy/" - } + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Create deep copies (clones) of your objects", - "homepage": "https://github.com/myclabs/DeepCopy", "keywords": [ "clone", "copy", @@ -153,7 +156,7 @@ "object", "object graph" ], - "time": "2017-04-12T18:52:22+00:00" + "time": "2017-10-19T19:58:43+00:00" }, { "name": "phar-io/manifest", @@ -313,29 +316,35 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.1.1", + "version": "4.2.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "2d3d238c433cf69caeb4842e97a3223a116f94b2" + "reference": "66465776cfc249844bde6d117abff1d22e06c2da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/2d3d238c433cf69caeb4842e97a3223a116f94b2", - "reference": "2d3d238c433cf69caeb4842e97a3223a116f94b2", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/66465776cfc249844bde6d117abff1d22e06c2da", + "reference": "66465776cfc249844bde6d117abff1d22e06c2da", "shasum": "" }, "require": { "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/reflection-common": "^1.0.0", "phpdocumentor/type-resolver": "^0.4.0", "webmozart/assert": "^1.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, "autoload": { "psr-4": { "phpDocumentor\\Reflection\\": [ @@ -354,7 +363,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-08-30T18:51:59+00:00" + "time": "2017-11-27T17:38:31+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -405,16 +414,16 @@ }, { "name": "phpspec/prophecy", - "version": "v1.7.2", + "version": "1.7.3", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6" + "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6", - "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", + "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", "shasum": "" }, "require": { @@ -426,7 +435,7 @@ }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8 || ^5.6.5" + "phpunit/phpunit": "^4.8.35 || ^5.7" }, "type": "library", "extra": { @@ -464,20 +473,20 @@ "spy", "stub" ], - "time": "2017-09-04T11:05:03+00:00" + "time": "2017-11-24T13:59:53+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "5.2.2", + "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "8ed1902a57849e117b5651fc1a5c48110946c06b" + "reference": "661f34d0bd3f1a7225ef491a70a020ad23a057a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/8ed1902a57849e117b5651fc1a5c48110946c06b", - "reference": "8ed1902a57849e117b5651fc1a5c48110946c06b", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/661f34d0bd3f1a7225ef491a70a020ad23a057a1", + "reference": "661f34d0bd3f1a7225ef491a70a020ad23a057a1", "shasum": "" }, "require": { @@ -486,14 +495,13 @@ "php": "^7.0", "phpunit/php-file-iterator": "^1.4.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^1.4.11 || ^2.0", + "phpunit/php-token-stream": "^2.0.1", "sebastian/code-unit-reverse-lookup": "^1.0.1", "sebastian/environment": "^3.0", "sebastian/version": "^2.0.1", "theseer/tokenizer": "^1.1" }, "require-dev": { - "ext-xdebug": "^2.5", "phpunit/phpunit": "^6.0" }, "suggest": { @@ -502,7 +510,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.2.x-dev" + "dev-master": "5.3.x-dev" } }, "autoload": { @@ -517,7 +525,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -528,20 +536,20 @@ "testing", "xunit" ], - "time": "2017-08-03T12:40:43+00:00" + "time": "2017-12-06T09:29:45+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.2", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", "shasum": "" }, "require": { @@ -575,7 +583,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03T07:40:28+00:00" + "time": "2017-11-27T13:52:08+00:00" }, { "name": "phpunit/php-text-template", @@ -669,16 +677,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "2.0.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0" + "reference": "791198a2c6254db10131eecfe8c06670700904db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9a02332089ac48e704c70f6cefed30c224e3c0b0", - "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", + "reference": "791198a2c6254db10131eecfe8c06670700904db", "shasum": "" }, "require": { @@ -714,20 +722,20 @@ "keywords": [ "tokenizer" ], - "time": "2017-08-20T05:47:52+00:00" + "time": "2017-11-27T05:48:46+00:00" }, { "name": "phpunit/phpunit", - "version": "6.4.3", + "version": "6.5.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "06b28548fd2b4a20c3cd6e247dc86331a7d4db13" + "reference": "83d27937a310f2984fd575686138597147bdc7df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/06b28548fd2b4a20c3cd6e247dc86331a7d4db13", - "reference": "06b28548fd2b4a20c3cd6e247dc86331a7d4db13", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/83d27937a310f2984fd575686138597147bdc7df", + "reference": "83d27937a310f2984fd575686138597147bdc7df", "shasum": "" }, "require": { @@ -741,12 +749,12 @@ "phar-io/version": "^1.0", "php": "^7.0", "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^5.2.2", - "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-code-coverage": "^5.3", + "phpunit/php-file-iterator": "^1.4.3", "phpunit/php-text-template": "^1.2.1", "phpunit/php-timer": "^1.0.9", - "phpunit/phpunit-mock-objects": "^4.0.3", - "sebastian/comparator": "^2.0.2", + "phpunit/phpunit-mock-objects": "^5.0.5", + "sebastian/comparator": "^2.1", "sebastian/diff": "^2.0", "sebastian/environment": "^3.1", "sebastian/exporter": "^3.1", @@ -772,7 +780,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.4.x-dev" + "dev-master": "6.5.x-dev" } }, "autoload": { @@ -798,33 +806,33 @@ "testing", "xunit" ], - "time": "2017-10-16T13:18:59+00:00" + "time": "2017-12-17T06:31:19+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "4.0.4", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "2f789b59ab89669015ad984afa350c4ec577ade0" + "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/2f789b59ab89669015ad984afa350c4ec577ade0", - "reference": "2f789b59ab89669015ad984afa350c4ec577ade0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/33fd41a76e746b8fa96d00b49a23dadfa8334cdf", + "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.5", "php": "^7.0", "phpunit/php-text-template": "^1.2.1", - "sebastian/exporter": "^3.0" + "sebastian/exporter": "^3.1" }, "conflict": { "phpunit/phpunit": "<6.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^6.5" }, "suggest": { "ext-soap": "*" @@ -832,7 +840,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "5.0.x-dev" } }, "autoload": { @@ -847,7 +855,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -857,7 +865,7 @@ "mock", "xunit" ], - "time": "2017-08-03T14:08:16+00:00" + "time": "2018-01-06T05:45:45+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -906,30 +914,30 @@ }, { "name": "sebastian/comparator", - "version": "2.0.2", + "version": "2.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "ae068fede81d06e7bb9bb46a367210a3d3e1fe6a" + "reference": "11c07feade1d65453e06df3b3b90171d6d982087" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/ae068fede81d06e7bb9bb46a367210a3d3e1fe6a", - "reference": "ae068fede81d06e7bb9bb46a367210a3d3e1fe6a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/11c07feade1d65453e06df3b3b90171d6d982087", + "reference": "11c07feade1d65453e06df3b3b90171d6d982087", "shasum": "" }, "require": { "php": "^7.0", "sebastian/diff": "^2.0", - "sebastian/exporter": "^3.0" + "sebastian/exporter": "^3.1" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.1.x-dev" } }, "autoload": { @@ -960,13 +968,13 @@ } ], "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", + "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], - "time": "2017-08-03T07:14:59+00:00" + "time": "2018-01-12T06:34:42+00:00" }, { "name": "sebastian/diff", From 92c16b23ab79ae4de7083f83ab3c44d6075c2f26 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 23 Jan 2018 11:56:12 +0000 Subject: [PATCH 159/225] Member vars of nested class are now processed correctly --- test/Sniffs/Classes/NoNullValuesUnitTest.inc.fixed | 2 +- test/Sniffs/Classes/NoNullValuesUnitTest.php | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/test/Sniffs/Classes/NoNullValuesUnitTest.inc.fixed b/test/Sniffs/Classes/NoNullValuesUnitTest.inc.fixed index b4aa4525..31c29706 100644 --- a/test/Sniffs/Classes/NoNullValuesUnitTest.inc.fixed +++ b/test/Sniffs/Classes/NoNullValuesUnitTest.inc.fixed @@ -19,7 +19,7 @@ class NoNullValues $var = null; $class = new class() { - private $s1 = null; + private $s1; }; $string = "String $var = null"; diff --git a/test/Sniffs/Classes/NoNullValuesUnitTest.php b/test/Sniffs/Classes/NoNullValuesUnitTest.php index 9ad06884..094d0b93 100644 --- a/test/Sniffs/Classes/NoNullValuesUnitTest.php +++ b/test/Sniffs/Classes/NoNullValuesUnitTest.php @@ -17,9 +17,7 @@ public function getErrorList($testFile = '') 9 => 1, 11 => 1, 13 => 1, - // @todo: Member vars of nested class are not processed correctly - // @see https://github.com/squizlabs/PHP_CodeSniffer/pull/1498 - // 23 => 1, + 23 => 1, ]; } From 72008100394c097614112d194fe6777c84f5b780 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 23 Jan 2018 13:14:11 +0000 Subject: [PATCH 160/225] Updated Functions Param and ReturnType Sniffs --- src/ZendCodingStandard/Helper/Methods.php | 14 -- .../Sniffs/Functions/ParamSniff.php | 114 ++++++---- .../Sniffs/Functions/ReturnTypeSniff.php | 106 +++++---- test/Sniffs/Functions/ParamUnitTest.1.inc | 116 ++++++++++ test/Sniffs/Functions/ParamUnitTest.inc | 25 +- test/Sniffs/Functions/ParamUnitTest.inc.fixed | 25 +- test/Sniffs/Functions/ParamUnitTest.php | 31 +-- .../Sniffs/Functions/ReturnTypeUnitTest.2.inc | 2 +- .../Sniffs/Functions/ReturnTypeUnitTest.3.inc | 214 ++++++++++++++++++ test/Sniffs/Functions/ReturnTypeUnitTest.inc | 38 +++- test/Sniffs/Functions/ReturnTypeUnitTest.php | 45 ++-- 11 files changed, 569 insertions(+), 161 deletions(-) create mode 100644 test/Sniffs/Functions/ParamUnitTest.1.inc create mode 100644 test/Sniffs/Functions/ReturnTypeUnitTest.3.inc diff --git a/src/ZendCodingStandard/Helper/Methods.php b/src/ZendCodingStandard/Helper/Methods.php index a1457a5c..6f23a445 100644 --- a/src/ZendCodingStandard/Helper/Methods.php +++ b/src/ZendCodingStandard/Helper/Methods.php @@ -124,20 +124,6 @@ trait Methods 'void', ]; - /** - * @var string[] - */ - private $needSpecificationTypes = [ - 'array', - '?array', - 'iterable', - '?iterable', - 'traversable', - '?traversable', - '\traversable', - '?\traversable', - ]; - /** * @param int $stackPtr */ diff --git a/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php index 112d1387..79325639 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php @@ -6,7 +6,9 @@ use ZendCodingStandard\Helper\Methods; use function array_filter; +use function array_merge; use function array_unique; +use function count; use function current; use function explode; use function implode; @@ -70,16 +72,15 @@ public function process(File $phpcsFile, $stackPtr) $this->params = $phpcsFile->getMethodParameters($stackPtr); if ($commentStart = $this->getCommentStart($phpcsFile, $stackPtr)) { - $this->processParamDoc($phpcsFile, $stackPtr, $commentStart); + $this->processParamDoc($phpcsFile, $commentStart); } $this->processParamSpec($phpcsFile); } /** - * @param int $stackPtr * @param int $commentStart */ - private function processParamDoc(File $phpcsFile, $stackPtr, $commentStart) + private function processParamDoc(File $phpcsFile, $commentStart) { $params = []; $paramsMap = []; @@ -307,14 +308,6 @@ private function checkParam( $param['name'], ]; $phpcsFile->addError($error, $param['token'], 'MissingSpecification', $data); - } elseif (in_array($lowerTypeHint, $this->needSpecificationTypes, true)) { - $type = strtr($lowerTypeHint, ['\\' => '', '?' => '']); - $code = sprintf('ParamType%sSpecification', ucfirst($type)); - $error = 'Parameter "%s" needs better specification in PHPDocs'; - $data = [ - $param['name'], - ]; - $phpcsFile->addError($error, $param['token'], $code, $data); } return; @@ -376,6 +369,19 @@ private function checkParam( } } + $cannotBeMixed = [ + 'array', + 'iterable', + 'mixed', + 'traversable', + '\traversable', + 'generator', + '\generator', + ]; + $hasNull = array_filter($types, function ($v) { + return strtolower($v) === 'null' || stripos($v, 'null[') === 0; + }); + $count = count($types); $break = false; foreach ($types as $key => $type) { $lower = strtolower($type); @@ -413,11 +419,19 @@ private function checkParam( continue; } - if ($lower === 'mixed' - || stripos($type, 'mixed[') === 0 + if ((($hasNull && $count > 2) + || ((! $hasNull + || ($lower === 'mixed' || strpos($lower, 'mixed[') === 0)) + && $count > 1)) + && array_filter($cannotBeMixed, function ($v) use ($lower) { + return $v === $lower || strpos($lower, $v . '[') === 0; + }) ) { - $error = 'Param type "mixed" is not allowed. Please specify the type.'; - $phpcsFile->addError($error, $tagPtr + 2, 'ParamDocMixed'); + $error = 'Param type "%s" is not allowed. Please specify the type.'; + $data = [ + $type, + ]; + $phpcsFile->addError($error, $tagPtr + 2, 'ParamDocMixed', $data); $break = true; continue; @@ -436,21 +450,6 @@ private function checkParam( continue; } - if (array_filter($this->needSpecificationTypes, function ($v) use ($lower) { - return $lower === $v || strpos($lower, $v . '[') === 0; - })) { - $type = str_replace('\\', '', $lower); - $code = sprintf('Param%sSpecification', ucfirst($type)); - $data = [ - stripos($type, 'traversable') !== false ? ucfirst($type) : $type, - ]; - $error = 'Param type "%s" needs better specification'; - $phpcsFile->addError($error, $tagPtr + 2, $code, $data); - - $break = true; - continue; - } - $suggestedType = $this->getSuggestedType($type); if ($suggestedType !== $type) { $error = 'Invalid param type; expected "%s", but found "%s"'; @@ -471,6 +470,8 @@ private function checkParam( } if ($typeHint) { + $simpleTypes = array_merge($this->simpleReturnTypes, ['mixed']); + // array if (in_array($lowerTypeHint, ['array', '?array'], true) && ! in_array($lower, ['null', 'array'], true) @@ -488,7 +489,7 @@ private function checkParam( // iterable if (in_array($lowerTypeHint, ['iterable', '?iterable'], true) - && in_array($lower, $this->simpleReturnTypes, true) + && in_array($lower, $simpleTypes, true) ) { $error = 'Param type contains "%s" which is not an iterable type'; $data = [ @@ -508,8 +509,7 @@ private function checkParam( '?\traversable', ], true) && ! in_array($lower, ['null', 'traversable', '\traversable'], true) - && (strpos($type, '[]') !== false - || in_array($lower, $this->simpleReturnTypes, true)) + && in_array($lower, $simpleTypes, true) ) { $error = 'Param type contains "%s" which is not a traversable type'; $data = [ @@ -521,13 +521,48 @@ private function checkParam( continue; } - if (! in_array($lowerTypeHint, $this->needSpecificationTypes, true) - && ((in_array($lowerTypeHint, $this->simpleReturnTypes, true) + // generator + if (in_array($lowerTypeHint, [ + 'generator', + '?generator', + '\generator', + '?\generator', + ], true) + && ! in_array($lower, ['null', 'generator', '\generator'], true) + && in_array($lower, array_merge($simpleTypes, ['mixed']), true) + ) { + $error = 'Param type contains %s which is not a generator type'; + $data = [ + $type, + ]; + $phpcsFile->addError($error, $tagPtr + 2, 'NotGeneratorType', $data); + + $break = true; + continue; + } + + $needSpecificationTypes = [ + 'array', + '?array', + 'iterable', + '?iterable', + 'traversable', + '?traversable', + '\traversable', + '?\traversable', + 'generator', + '?generator', + '\generator', + '?\generator', + ]; + + if (! in_array($lowerTypeHint, $needSpecificationTypes, true) + && ((in_array($lowerTypeHint, $simpleTypes, true) && $lower !== 'null' && $lower !== $lowerTypeHint && '?' . $lower !== $lowerTypeHint) - || (! in_array($lowerTypeHint, $this->simpleReturnTypes, true) - && array_filter($this->simpleReturnTypes, function ($v) use ($lower) { + || (! in_array($lowerTypeHint, $simpleTypes, true) + && array_filter($simpleTypes, function ($v) use ($lower) { return $v === $lower || strpos($lower, $v . '[') === 0; }))) ) { @@ -570,10 +605,7 @@ private function checkParam( } // Check if PHPDocs param is required - if ($typeHint - && ! in_array($lowerTypeHint, $this->needSpecificationTypes, true) - && ! $description - ) { + if ($typeHint && ! $description) { $tmpTypeHint = $typeHint; if (isset($param['default']) && strtolower($param['default']) === 'null' diff --git a/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php index 10c60967..6be7cdd9 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php @@ -8,6 +8,7 @@ use function array_filter; use function array_intersect; +use function array_merge; use function array_udiff; use function array_unique; use function count; @@ -20,7 +21,6 @@ use function preg_replace; use function preg_split; use function sprintf; -use function str_replace; use function strcasecmp; use function stripos; use function strpos; @@ -247,16 +247,38 @@ private function processReturnDoc(File $phpcsFile, $commentStart) return; } + $cannotBeMixed = [ + 'mixed', + 'array', + 'iterable', + 'traversable', + '\traversable', + 'generator', + '\generator', + ]; + $hasInvalidType = false; $this->returnDocTypes = explode('|', $this->returnDocValue); + $count = count($this->returnDocTypes); + $hasNull = array_filter($this->returnDocTypes, function ($v) { + return strtolower($v) === 'null' || stripos($v, 'null[') === 0; + }); foreach ($this->returnDocTypes as $key => $type) { $lower = strtolower($type); - if ($lower === 'mixed' - || strpos($lower, 'mixed[') === 0 + if ((($hasNull && $count > 2) + || ((! $hasNull + || ($lower === 'mixed' || strpos($lower, 'mixed[') === 0)) + && $count > 1)) + && array_filter($cannotBeMixed, function ($v) use ($lower) { + return $v === $lower || strpos($lower, $v . '[') === 0; + }) ) { - $error = 'Return type "mixed" type is not allowed. Please specify the type.'; - $phpcsFile->addError($error, $returnDoc + 2, 'ReturnMixed'); + $error = 'Return type "%s" cannot be mixed with other types.'; + $data = [ + $type, + ]; + $phpcsFile->addError($error, $returnDoc + 2, 'ReturnMixed', $data); $hasInvalidType = true; continue; @@ -271,21 +293,6 @@ private function processReturnDoc(File $phpcsFile, $commentStart) continue; } - if (array_filter($this->needSpecificationTypes, function ($v) use ($type) { - return strtolower($type) === $v || stripos($type, $v . '[') === 0; - })) { - $type = str_replace('\\', '', strtolower($type)); - $code = sprintf('Return%sSpecification', ucfirst($type)); - $data = [ - stripos($type, 'traversable') !== false ? ucfirst($type) : $type, - ]; - $error = 'Return type "%s" needs better specification'; - $phpcsFile->addError($error, $returnDoc + 2, $code, $data); - - $hasInvalidType = true; - continue; - } - if (in_array(strtolower($type), ['null', 'true', 'false'], true)) { $suggestedType = strtolower($type); } else { @@ -465,20 +472,6 @@ private function processReturnType(File $phpcsFile, $stackPtr) return; } - if (! $this->returnDoc - && in_array($lowerReturnTypeValue, $this->needSpecificationTypes, true) - ) { - $type = strtr($lowerReturnTypeValue, ['\\' => '', '?' => '']); - $code = sprintf('ReturnType%sSpecification', ucfirst($type)); - $error = 'Return type "%s" needs better specification in PHPDocs.'; - $data = [ - $type === 'traversable' ? ucfirst($type) : $type, - ]; - $phpcsFile->addError($error, $returnType, $code, $data); - - return; - } - if (! $this->returnDoc || ! $this->returnDocIsValid) { return; } @@ -518,7 +511,22 @@ private function processReturnType(File $phpcsFile, $stackPtr) return; } - if (! in_array($lowerReturnTypeValue, $this->needSpecificationTypes, true)) { + $needSpecificationTypes = [ + 'array', + '?array', + 'iterable', + '?iterable', + 'traversable', + '?traversable', + '\traversable', + '?\traversable', + 'generator', + '?generator', + '\generator', + '?\generator', + ]; + + if (! in_array($lowerReturnTypeValue, $needSpecificationTypes, true)) { if ($this->typesMatch($this->returnTypeValue, $this->returnDocValue)) { // There is no description and values are the same so PHPDoc tag is redundant. if (! $this->returnDocDescription) { @@ -602,6 +610,8 @@ private function processReturnType(File $phpcsFile, $stackPtr) return; } + $simpleTypes = array_merge($this->simpleReturnTypes, ['mixed']); + switch ($lowerReturnTypeValue) { case 'array': case '?array': @@ -628,7 +638,7 @@ private function processReturnType(File $phpcsFile, $stackPtr) continue; } - if (in_array($lower, $this->simpleReturnTypes, true)) { + if (in_array($lower, $simpleTypes, true)) { $error = 'Return type contains "%s" which is not an iterable type'; $data = [ $type, @@ -648,9 +658,7 @@ private function processReturnType(File $phpcsFile, $stackPtr) continue; } - if (strpos($type, '[]') !== false - || in_array($lower, $this->simpleReturnTypes, true) - ) { + if (in_array($lower, $simpleTypes, true)) { $error = 'Return type contains "%s" which is not a traversable type'; $data = [ $type, @@ -659,6 +667,26 @@ private function processReturnType(File $phpcsFile, $stackPtr) } } break; + + case 'generator': + case '?generator': + case '\generator': + case '?\generator': + foreach ($this->returnDocTypes as $type) { + $lower = strtolower($type); + if (in_array($lower, ['null', 'generator', '\generator'], true)) { + continue; + } + + if (in_array($lower, $simpleTypes, true)) { + $error = 'Return type contains "%s" which is not a generator type'; + $data = [ + $type, + ]; + $phpcsFile->addError($error, $this->returnDoc + 2, 'NotGeneratorType', $data); + } + } + break; } } diff --git a/test/Sniffs/Functions/ParamUnitTest.1.inc b/test/Sniffs/Functions/ParamUnitTest.1.inc new file mode 100644 index 00000000..1ae9d47b --- /dev/null +++ b/test/Sniffs/Functions/ParamUnitTest.1.inc @@ -0,0 +1,116 @@ + 2, + 23 => 1, + 28 => 1, + 33 => 1, + 38 => 1, + 48 => 1, + 58 => 1, + 68 => 1, + 78 => 1, + 88 => 1, + 98 => 1, + 108 => 1, + 113 => 1, + ]; + } return [ 18 => 1, - 20 => 1, - 23 => 1, 33 => 1, - 37 => 1, - 40 => 1, 50 => 3, - 54 => 1, - 57 => 1, 67 => 1, - 72 => 1, - 77 => 1, 81 => 1, - 83 => 1, 85 => 3, 93 => 1, 98 => 1, - 103 => 1, 108 => 1, 110 => 1, 113 => 1, @@ -78,9 +86,6 @@ public function getErrorList($testFile = '') 226 => 1, 227 => 1, 232 => 1, - 233 => 1, - 234 => 1, - 235 => 1, 245 => 1, 246 => 1, 247 => 1, diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.2.inc b/test/Sniffs/Functions/ReturnTypeUnitTest.2.inc index b787f453..2020cea8 100644 --- a/test/Sniffs/Functions/ReturnTypeUnitTest.2.inc +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.2.inc @@ -15,7 +15,7 @@ abstract class FunctionCommentReturn abstract public function nullArrayTypeSpecification() : ?array; /** - * @return iterable|string|MyIterableClass|\DateTime[] + * @return iterable|string|\DateTime[]|MyIterableClass */ abstract public function iterableTypeSpecification() : iterable; diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.3.inc b/test/Sniffs/Functions/ReturnTypeUnitTest.3.inc new file mode 100644 index 00000000..a7a5e87f --- /dev/null +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.3.inc @@ -0,0 +1,214 @@ + 1, 18 => 2, 23 => 1, - 28 => 4, - 33 => 3, + 28 => 2, + 33 => 2, 42 => 1, 43 => 1, 44 => 1, @@ -137,10 +137,6 @@ public function getErrorList($testFile = '') 116 => 2, 124 => 2, 132 => 1, - 139 => 1, - 148 => 1, - 157 => 1, - 166 => 1, 176 => 1, 184 => 1, 188 => 1, @@ -173,6 +169,21 @@ public function getErrorList($testFile = '') 459 => 2, 467 => 2, ]; + case 'ReturnTypeUnitTest.3.inc': + return [ + 24 => 2, + 32 => 1, + 40 => 1, + 48 => 1, + 64 => 1, + 80 => 1, + 96 => 1, + 112 => 1, + 136 => 1, + 160 => 1, + 184 => 1, + 200 => 1, + ]; } return [ @@ -204,25 +215,9 @@ public function getErrorList($testFile = '') 210 => 1, 215 => 1, 220 => 1, - 225 => 1, - 230 => 1, - 234 => 1, - 236 => 1, - 238 => 1, - 240 => 1, - 242 => 1, - 244 => 1, - 246 => 1, - 248 => 1, - 251 => 1, - 256 => 1, - 261 => 1, - 266 => 1, - 271 => 1, - 276 => 1, - 281 => 6, - 286 => 2, - 294 => 1, + 299 => 6, + 304 => 2, + 312 => 1, ]; } From a2bb0f8207c1dfe922e21bee77e04f5a581f82bc Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 13 Feb 2018 11:38:54 +0000 Subject: [PATCH 161/225] Fixed ScopeIndent sniff --- .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 14 ++++++++++---- src/ZendCodingStandard/ruleset.xml | 1 + test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc | 6 ++++++ .../WhiteSpace/ScopeIndentUnitTest.inc.fixed | 6 ++++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index 8e04637f..0ce4b98e 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -731,7 +731,11 @@ private function fp(File $phpcsFile, $ptr) $ptr = $tokens[$ptr]['bracket_opener']; } elseif ($tokens[$ptr]['code'] === T_OBJECT_OPERATOR) { return $tokens[$ptr]['column']; - } elseif ($tokens[$ptr]['code'] === T_SEMICOLON) { + } elseif (in_array( + $tokens[$ptr]['code'], + [T_SEMICOLON, T_OPEN_PARENTHESIS], + true + )) { break; } } @@ -755,9 +759,11 @@ private function np(File $phpcsFile, $ptr) $ptr = $tokens[$ptr]['parenthesis_closer']; } elseif ($tokens[$ptr]['code'] === T_OPEN_CURLY_BRACKET) { $ptr = $tokens[$ptr]['bracket_closer']; - } elseif ($tokens[$ptr]['code'] === T_OBJECT_OPERATOR - || $tokens[$ptr]['code'] === T_SEMICOLON - ) { + } elseif (in_array( + $tokens[$ptr]['code'], + [T_OBJECT_OPERATOR, T_SEMICOLON, T_CLOSE_PARENTHESIS], + true + )) { return $ptr; } } diff --git a/src/ZendCodingStandard/ruleset.xml b/src/ZendCodingStandard/ruleset.xml index f87381fb..c72b21a4 100755 --- a/src/ZendCodingStandard/ruleset.xml +++ b/src/ZendCodingStandard/ruleset.xml @@ -15,6 +15,7 @@ + diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc index 1de8625f..700e2872 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc @@ -500,3 +500,9 @@ function test2() return 0; } + +$response = $handler->handle( + $request + ->withMethod(RequestMethod::METHOD_GET) + ->withAttribute(self::FORWARDED_HTTP_METHOD_ATTRIBUTE, RequestMethod::METHOD_HEAD) +); diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed index ff686179..dc3b698a 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed @@ -498,3 +498,9 @@ function test2() return 0; } + +$response = $handler->handle( + $request + ->withMethod(RequestMethod::METHOD_GET) + ->withAttribute(self::FORWARDED_HTTP_METHOD_ATTRIBUTE, RequestMethod::METHOD_HEAD) +); From 212999a72e3969c5e5b5047e8810b1f153c3d655 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 13 Feb 2018 11:44:16 +0000 Subject: [PATCH 162/225] Updated dependencies and Travis CI configuration --- .travis.yml | 16 ++--- composer.json | 5 +- composer.lock | 169 +++++++++++++++++++++++++------------------------- 3 files changed, 91 insertions(+), 99 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8f786309..f518cc12 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,12 +5,11 @@ language: php cache: directories: - $HOME/.composer/cache - - vendor env: global: - COMPOSER_ARGS="--no-interaction" - - COVERAGE_DEPS="satooshi/php-coveralls" + - COVERAGE_DEPS="php-coveralls/php-coveralls" matrix: include: @@ -20,7 +19,7 @@ matrix: - php: 5.6 env: - DEPS=locked - - LEGACY_DEPS="phpunit/phpunit" + - LEGACY_DEPS="doctrine/instantiator phpunit/phpunit" - php: 5.6 env: - DEPS=latest @@ -30,9 +29,7 @@ matrix: - php: 7 env: - DEPS=locked - - LEGACY_DEPS="doctrine/instantiator" - - CS_CHECK=true - - TEST_COVERAGE=true + - LEGACY_DEPS="doctrine/instantiator phpunit/phpunit" - php: 7 env: - DEPS=latest @@ -42,6 +39,8 @@ matrix: - php: 7.1 env: - DEPS=locked + - CS_CHECK=true + - TEST_COVERAGE=true - php: 7.1 env: - DEPS=latest @@ -54,12 +53,9 @@ matrix: - php: 7.2 env: - DEPS=latest - allow_failures: - - php: 7.2 before_install: - if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi - - travis_retry composer self-update install: - travis_retry composer install $COMPOSER_ARGS --ignore-platform-reqs @@ -74,7 +70,7 @@ script: - if [[ $CS_CHECK == 'true' ]]; then composer cs-check ; fi after_script: - - if [[ $TEST_COVERAGE == 'true' ]]; then composer upload-coverage ; fi + - if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry php vendor/bin/php-coveralls -v ; fi notifications: email: false diff --git a/composer.json b/composer.json index 4bcd40e8..943ae69d 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "squizlabs/php_codesniffer": "3.2.2" }, "require-dev": { - "phpunit/phpunit": "^5.7.26 || ^6.5.5" + "phpunit/phpunit": "^5.7.27 || ^6.5.6 || ^7.0.1" }, "autoload": { "psr-4": { @@ -35,7 +35,6 @@ "cs-check": "phpcs", "cs-fix": "phpcbf", "test": "phpunit --colors=always", - "test-coverage": "phpunit --colors=always --coverage-clover clover.xml", - "upload-coverage": "coveralls -v" + "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" } } diff --git a/composer.lock b/composer.lock index 4b723a72..7f94066d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "d5669c04b0f4337e5e2f0e6c06be4c5c", + "content-hash": "19e18b2f9302005e2361fd387727905e", "packages": [ { "name": "squizlabs/php_codesniffer", @@ -316,16 +316,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.2.0", + "version": "4.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "66465776cfc249844bde6d117abff1d22e06c2da" + "reference": "94fd0001232e47129dd3504189fa1c7225010d08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/66465776cfc249844bde6d117abff1d22e06c2da", - "reference": "66465776cfc249844bde6d117abff1d22e06c2da", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08", "shasum": "" }, "require": { @@ -363,7 +363,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-11-27T17:38:31+00:00" + "time": "2017-11-30T07:14:17+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -414,16 +414,16 @@ }, { "name": "phpspec/prophecy", - "version": "1.7.3", + "version": "1.7.4", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf" + "reference": "9f901e29c93dae4aa77c0bb161df4276f9c9a1be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", - "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/9f901e29c93dae4aa77c0bb161df4276f9c9a1be", + "reference": "9f901e29c93dae4aa77c0bb161df4276f9c9a1be", "shasum": "" }, "require": { @@ -435,7 +435,7 @@ }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" }, "type": "library", "extra": { @@ -473,44 +473,44 @@ "spy", "stub" ], - "time": "2017-11-24T13:59:53+00:00" + "time": "2018-02-11T18:49:29+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "5.3.0", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "661f34d0bd3f1a7225ef491a70a020ad23a057a1" + "reference": "f8ca4b604baf23dab89d87773c28cc07405189ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/661f34d0bd3f1a7225ef491a70a020ad23a057a1", - "reference": "661f34d0bd3f1a7225ef491a70a020ad23a057a1", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f8ca4b604baf23dab89d87773c28cc07405189ba", + "reference": "f8ca4b604baf23dab89d87773c28cc07405189ba", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", - "php": "^7.0", + "php": "^7.1", "phpunit/php-file-iterator": "^1.4.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^2.0.1", + "phpunit/php-token-stream": "^3.0", "sebastian/code-unit-reverse-lookup": "^1.0.1", "sebastian/environment": "^3.0", "sebastian/version": "^2.0.1", "theseer/tokenizer": "^1.1" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^7.0" }, "suggest": { - "ext-xdebug": "^2.5.5" + "ext-xdebug": "^2.6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.3.x-dev" + "dev-master": "6.0-dev" } }, "autoload": { @@ -536,7 +536,7 @@ "testing", "xunit" ], - "time": "2017-12-06T09:29:45+00:00" + "time": "2018-02-02T07:01:41+00:00" }, { "name": "phpunit/php-file-iterator", @@ -628,28 +628,28 @@ }, { "name": "phpunit/php-timer", - "version": "1.0.9", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b8454ea6958c3dee38453d3bd571e023108c91f", + "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -664,7 +664,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -673,33 +673,33 @@ "keywords": [ "timer" ], - "time": "2017-02-26T11:10:40+00:00" + "time": "2018-02-01T13:07:23+00:00" }, { "name": "phpunit/php-token-stream", - "version": "2.0.2", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "791198a2c6254db10131eecfe8c06670700904db" + "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", - "reference": "791198a2c6254db10131eecfe8c06670700904db", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/21ad88bbba7c3d93530d93994e0a33cd45f02ace", + "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": "^7.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^6.2.4" + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -722,20 +722,20 @@ "keywords": [ "tokenizer" ], - "time": "2017-11-27T05:48:46+00:00" + "time": "2018-02-01T13:16:43+00:00" }, { "name": "phpunit/phpunit", - "version": "6.5.5", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "83d27937a310f2984fd575686138597147bdc7df" + "reference": "316555dbd0ed4097bbdd17c65ab416bf27a472e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/83d27937a310f2984fd575686138597147bdc7df", - "reference": "83d27937a310f2984fd575686138597147bdc7df", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/316555dbd0ed4097bbdd17c65ab416bf27a472e9", + "reference": "316555dbd0ed4097bbdd17c65ab416bf27a472e9", "shasum": "" }, "require": { @@ -747,15 +747,15 @@ "myclabs/deep-copy": "^1.6.1", "phar-io/manifest": "^1.0.1", "phar-io/version": "^1.0", - "php": "^7.0", + "php": "^7.1", "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^5.3", + "phpunit/php-code-coverage": "^6.0", "phpunit/php-file-iterator": "^1.4.3", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^1.0.9", - "phpunit/phpunit-mock-objects": "^5.0.5", + "phpunit/php-timer": "^2.0", + "phpunit/phpunit-mock-objects": "^6.0", "sebastian/comparator": "^2.1", - "sebastian/diff": "^2.0", + "sebastian/diff": "^3.0", "sebastian/environment": "^3.1", "sebastian/exporter": "^3.1", "sebastian/global-state": "^2.0", @@ -763,16 +763,12 @@ "sebastian/resource-operations": "^1.0", "sebastian/version": "^2.0.1" }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2", - "phpunit/dbunit": "<3.0" - }, "require-dev": { "ext-pdo": "*" }, "suggest": { "ext-xdebug": "*", - "phpunit/php-invoker": "^1.1" + "phpunit/php-invoker": "^2.0" }, "bin": [ "phpunit" @@ -780,7 +776,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.5.x-dev" + "dev-master": "7.0-dev" } }, "autoload": { @@ -806,33 +802,30 @@ "testing", "xunit" ], - "time": "2017-12-17T06:31:19+00:00" + "time": "2018-02-13T06:08:08+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "5.0.6", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf" + "reference": "e495e5d3660321b62c294d8c0e954d02d6ce2573" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/33fd41a76e746b8fa96d00b49a23dadfa8334cdf", - "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/e495e5d3660321b62c294d8c0e954d02d6ce2573", + "reference": "e495e5d3660321b62c294d8c0e954d02d6ce2573", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.5", - "php": "^7.0", + "php": "^7.1", "phpunit/php-text-template": "^1.2.1", "sebastian/exporter": "^3.1" }, - "conflict": { - "phpunit/phpunit": "<6.0" - }, "require-dev": { - "phpunit/phpunit": "^6.5" + "phpunit/phpunit": "^7.0" }, "suggest": { "ext-soap": "*" @@ -840,7 +833,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0.x-dev" + "dev-master": "6.0.x-dev" } }, "autoload": { @@ -865,7 +858,7 @@ "mock", "xunit" ], - "time": "2018-01-06T05:45:45+00:00" + "time": "2018-02-01T13:11:13+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -914,21 +907,21 @@ }, { "name": "sebastian/comparator", - "version": "2.1.2", + "version": "2.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "11c07feade1d65453e06df3b3b90171d6d982087" + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/11c07feade1d65453e06df3b3b90171d6d982087", - "reference": "11c07feade1d65453e06df3b3b90171d6d982087", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", "shasum": "" }, "require": { "php": "^7.0", - "sebastian/diff": "^2.0", + "sebastian/diff": "^2.0 || ^3.0", "sebastian/exporter": "^3.1" }, "require-dev": { @@ -974,32 +967,33 @@ "compare", "equality" ], - "time": "2018-01-12T06:34:42+00:00" + "time": "2018-02-01T13:46:46+00:00" }, { "name": "sebastian/diff", - "version": "2.0.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" + "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/e09160918c66281713f1c324c1f4c4c3037ba1e8", + "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^6.2" + "phpunit/phpunit": "^7.0", + "symfony/process": "^2 || ^3.3 || ^4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1024,9 +1018,12 @@ "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ - "diff" + "diff", + "udiff", + "unidiff", + "unified diff" ], - "time": "2017-08-03T08:09:46+00:00" + "time": "2018-02-01T13:45:15+00:00" }, { "name": "sebastian/environment", @@ -1468,16 +1465,16 @@ }, { "name": "webmozart/assert", - "version": "1.2.0", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" + "reference": "0df1908962e7a3071564e857d86874dad1ef204a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", + "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a", "shasum": "" }, "require": { @@ -1514,7 +1511,7 @@ "check", "validate" ], - "time": "2016-11-23T20:04:58+00:00" + "time": "2018-01-29T19:49:41+00:00" } ], "aliases": [], From b877f17438e5092165833b834c785b21f95bb7da Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 13 Feb 2018 13:28:57 +0000 Subject: [PATCH 163/225] Allow mixing array|iterable|\Generator|\Traversable with other types Technically it is possible, but usualy it's not a good practice. --- .../Sniffs/Functions/ParamSniff.php | 23 +++-------------- .../Sniffs/Functions/ReturnTypeSniff.php | 25 +++---------------- test/Sniffs/Functions/ParamUnitTest.1.inc | 20 +++++++++++++++ test/Sniffs/Functions/ParamUnitTest.php | 2 +- test/Sniffs/Functions/ReturnTypeUnitTest.inc | 13 ++++++++++ test/Sniffs/Functions/ReturnTypeUnitTest.php | 14 +++++------ 6 files changed, 47 insertions(+), 50 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php index 79325639..ee115c40 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php @@ -369,18 +369,6 @@ private function checkParam( } } - $cannotBeMixed = [ - 'array', - 'iterable', - 'mixed', - 'traversable', - '\traversable', - 'generator', - '\generator', - ]; - $hasNull = array_filter($types, function ($v) { - return strtolower($v) === 'null' || stripos($v, 'null[') === 0; - }); $count = count($types); $break = false; foreach ($types as $key => $type) { @@ -419,15 +407,10 @@ private function checkParam( continue; } - if ((($hasNull && $count > 2) - || ((! $hasNull - || ($lower === 'mixed' || strpos($lower, 'mixed[') === 0)) - && $count > 1)) - && array_filter($cannotBeMixed, function ($v) use ($lower) { - return $v === $lower || strpos($lower, $v . '[') === 0; - }) + if ($count > 1 + && ($lower === 'mixed' || strpos($lower, 'mixed[') === 0) ) { - $error = 'Param type "%s" is not allowed. Please specify the type.'; + $error = 'Param type "%s" cannot be mixed with other types.'; $data = [ $type, ]; diff --git a/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php index 6be7cdd9..ba4c3cbe 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php @@ -22,7 +22,6 @@ use function preg_split; use function sprintf; use function strcasecmp; -use function stripos; use function strpos; use function strtolower; use function strtr; @@ -247,34 +246,16 @@ private function processReturnDoc(File $phpcsFile, $commentStart) return; } - $cannotBeMixed = [ - 'mixed', - 'array', - 'iterable', - 'traversable', - '\traversable', - 'generator', - '\generator', - ]; - $hasInvalidType = false; $this->returnDocTypes = explode('|', $this->returnDocValue); $count = count($this->returnDocTypes); - $hasNull = array_filter($this->returnDocTypes, function ($v) { - return strtolower($v) === 'null' || stripos($v, 'null[') === 0; - }); foreach ($this->returnDocTypes as $key => $type) { $lower = strtolower($type); - if ((($hasNull && $count > 2) - || ((! $hasNull - || ($lower === 'mixed' || strpos($lower, 'mixed[') === 0)) - && $count > 1)) - && array_filter($cannotBeMixed, function ($v) use ($lower) { - return $v === $lower || strpos($lower, $v . '[') === 0; - }) + if ($count > 1 + && ($lower === 'mixed' || strpos($lower, 'mixed[') === 0) ) { - $error = 'Return type "%s" cannot be mixed with other types.'; + $error = 'Return type %s cannot be mixed with other types.'; $data = [ $type, ]; diff --git a/test/Sniffs/Functions/ParamUnitTest.1.inc b/test/Sniffs/Functions/ParamUnitTest.1.inc index 1ae9d47b..766c4b8a 100644 --- a/test/Sniffs/Functions/ParamUnitTest.1.inc +++ b/test/Sniffs/Functions/ParamUnitTest.1.inc @@ -113,4 +113,24 @@ class FunctionParam * @param MyObj $x */ public function test22(array $x) {} + + /** + * @param array|callable $a + */ + public function paramArrayWithOtherTypes($a) {} + + /** + * @param callable|iterable $a + */ + public function paramIterableWithOtherTypes($a) {} + + /** + * @param int|\Traversable $a + */ + public function paramTraversableWithOtherTypes($a) {} + + /** + * @param float|\Generator $a + */ + public function paramGeneratorWithOtherTypes($a) {} } diff --git a/test/Sniffs/Functions/ParamUnitTest.php b/test/Sniffs/Functions/ParamUnitTest.php index ecebf187..a1cecbb5 100644 --- a/test/Sniffs/Functions/ParamUnitTest.php +++ b/test/Sniffs/Functions/ParamUnitTest.php @@ -32,7 +32,7 @@ public function getErrorList($testFile = '') return [ 18 => 1, 33 => 1, - 50 => 3, + 50 => 2, 67 => 1, 81 => 1, 85 => 3, diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.inc b/test/Sniffs/Functions/ReturnTypeUnitTest.inc index 10402250..79439032 100644 --- a/test/Sniffs/Functions/ReturnTypeUnitTest.inc +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.inc @@ -315,4 +315,17 @@ abstract class FunctionCommentReturn { return mt_rand(0, 1) ? null : false; } + + /** + * @return array|callable|iterable|\Generator|\Traversable + */ + public function returnArrayOrSomethingElse($x) + { + if ($x) { + return function() { + }; + } + + return []; + } } diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.php b/test/Sniffs/Functions/ReturnTypeUnitTest.php index f1920ad8..5e4e0d92 100644 --- a/test/Sniffs/Functions/ReturnTypeUnitTest.php +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.php @@ -96,11 +96,11 @@ public function getErrorList($testFile = '') ]; case 'ReturnTypeUnitTest.2.inc': return [ - 8 => 3, + 8 => 2, 13 => 1, - 18 => 2, + 18 => 1, 23 => 1, - 28 => 2, + 28 => 1, 33 => 2, 42 => 1, 43 => 1, @@ -134,15 +134,15 @@ public function getErrorList($testFile = '') 104 => 1, 108 => 1, 112 => 1, - 116 => 2, - 124 => 2, + 116 => 1, + 124 => 1, 132 => 1, 176 => 1, 184 => 1, 188 => 1, 192 => 1, 196 => 1, - 200 => 2, + 200 => 1, 204 => 1, 213 => 1, 216 => 1, @@ -215,7 +215,7 @@ public function getErrorList($testFile = '') 210 => 1, 215 => 1, 220 => 1, - 299 => 6, + 299 => 2, 304 => 2, 312 => 1, ]; From 2aa1d148b2eee4e821ccaf65fd0fa852e99eaae8 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 14 Feb 2018 08:23:44 +0000 Subject: [PATCH 164/225] Added support for defining array values /** * @param array $variable { * @var bool $required Whether this element is required * @var string $label The display name for this element * } */ --- .../Sniffs/Commenting/DocCommentSniff.php | 61 ++++++++++++++----- .../Commenting/FunctionCommentSniff.php | 48 ++++++++++++++- test/Sniffs/Commenting/DocCommentUnitTest.inc | 13 ++++ .../Commenting/DocCommentUnitTest.inc.fixed | 13 ++++ test/Sniffs/Commenting/DocCommentUnitTest.php | 1 + .../Commenting/FunctionCommentUnitTest.inc | 12 ++++ .../FunctionCommentUnitTest.inc.fixed | 12 ++++ .../Commenting/FunctionCommentUnitTest.php | 1 + .../Sniffs/Functions/ReturnTypeUnitTest.3.inc | 11 ++++ 9 files changed, 154 insertions(+), 18 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index c0053243..c1e41311 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -7,15 +7,16 @@ use function array_filter; use function implode; use function in_array; -use function ltrim; use function max; use function preg_match; +use function preg_replace; use function preg_split; use function round; use function str_repeat; use function strlen; use function strpos; use function strtolower; +use function substr; use function trim; use const T_DOC_COMMENT_CLOSE_TAG; @@ -377,6 +378,10 @@ private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEn { $tokens = $phpcsFile->getTokens(); + $firstTag = isset($tokens[$commentStart]['comment_tags'][0]) + ? $tokens[$commentStart]['comment_tags'][0] + : null; + $next = $commentStart; $search = [T_DOC_COMMENT_STAR, T_DOC_COMMENT_CLOSE_TAG]; while ($next = $phpcsFile->findNext($search, $next + 1, $commentEnd + 1)) { @@ -385,19 +390,41 @@ private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEn || ($tokens[$next + 1]['code'] === T_DOC_COMMENT_WHITESPACE && strpos($tokens[$next + 1]['content'], $phpcsFile->eolChar) === false) ) { + $nested = 0; + if ($firstTag) { + $prev = $next; + while ($prev = $phpcsFile->findPrevious(T_DOC_COMMENT_STRING, $prev - 1, $firstTag)) { + if ($tokens[$prev]['content'][0] === '}') { + --$nested; + } + if (substr($tokens[$prev]['content'], -1) === '{') { + ++$nested; + } + } + } + + $expectedSpaces = 1 + $this->indent * $nested; + $expected = str_repeat(' ', $expectedSpaces); + if ($tokens[$next + 1]['code'] !== T_DOC_COMMENT_WHITESPACE) { - $error = 'There must be exactly one space between star and comment.'; - $fix = $phpcsFile->addFixableError($error, $next, 'NoSpaceAfterStar'); + $error = 'There must be exactly %d space(s) between star and comment; found 0'; + $data = [ + $expectedSpaces, + ]; + $fix = $phpcsFile->addFixableError($error, $next, 'NoSpaceAfterStar', $data); if ($fix) { - $phpcsFile->fixer->addContent($next, ' '); + $phpcsFile->fixer->addContent($next, $expected); } - } elseif ($tokens[$next + 1]['content'] !== ' ' + } elseif ($tokens[$next + 1]['content'] !== $expected && ($tokens[$next + 2]['content'][0] === '@' || $tokens[$next + 1]['line'] === $tokens[$commentStart]['line'] + 1) ) { - $error = 'There must be exactly one space between star and comment.'; - $fix = $phpcsFile->addFixableError($error, $next + 1, 'TooManySpacesAfterStar'); + $error = 'There must be exactly %d space(s) between star and comment'; + $data = [ + $expectedSpaces, + ]; + $fix = $phpcsFile->addFixableError($error, $next + 1, 'TooManySpacesAfterStar', $data); if ($fix) { $phpcsFile->fixer->replaceToken($next + 1, ' '); @@ -416,14 +443,20 @@ private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEn true ); - $trimmed = ltrim($tokens[$next + 1]['content']); - $spaces = strlen($tokens[$next + 1]['content']) - strlen($trimmed); + if ($tokens[$next + 2]['content'][0] === '}') { + $expectedSpaces -= $this->indent; + } else { + $expectedSpaces += $this->indent; + } + + $spaces = strlen(preg_replace('/^( *).*$/', '\\1', $tokens[$next + 1]['content'])); if ($tokens[$prev]['code'] === T_DOC_COMMENT_TAG - && ($spaces < $this->indent + 1 + && ($spaces < $expectedSpaces || (($spaces - 1) % $this->indent) !== 0 - || ($spaces > $this->indent + 1 + || ($spaces > $expectedSpaces && $tokens[$prev]['line'] === $tokens[$next + 1]['line'] - 1)) ) { + // could be doc string or tag $prev2 = $phpcsFile->findPrevious( [ T_DOC_COMMENT_WHITESPACE, @@ -435,9 +468,7 @@ private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEn ); if ($tokens[$prev2]['line'] === $tokens[$next]['line'] - 1) { - if ($tokens[$prev]['line'] === $tokens[$next + 1]['line'] - 1) { - $expectedSpaces = 1 + $this->indent; - } else { + if ($tokens[$prev]['line'] !== $tokens[$next + 1]['line'] - 1) { $expectedSpaces = 1 + max( round(($spaces - 1) / $this->indent) * $this->indent, $this->indent @@ -451,7 +482,7 @@ private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEn $fix = $phpcsFile->addFixableError($error, $next + 1, 'InvalidDescriptionIndent', $data); if ($fix) { - $phpcsFile->fixer->replaceToken($next + 1, str_repeat(' ', $expectedSpaces) . $trimmed); + $phpcsFile->fixer->replaceToken($next + 1, str_repeat(' ', $expectedSpaces)); } } else { $error = 'Additional description is not allowed after tag.' diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index b1994f51..5419bc67 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -10,8 +10,10 @@ use function current; use function in_array; use function key; +use function next; use function strpos; use function strtolower; +use function substr; use function uasort; use const T_COMMENT; @@ -112,7 +114,8 @@ private function processTagOrder(File $phpcsFile, $commentStart) $tags = $tokens[$commentStart]['comment_tags']; $data = []; - foreach ($tags as $key => $tag) { + while ($tag = current($tags)) { + $key = key($tags); if (isset($tags[$key + 1])) { $lastFrom = $tags[$key + 1]; } else { @@ -125,16 +128,55 @@ private function processTagOrder(File $phpcsFile, $commentStart) null, true ); + + // if the last character of the description is { + // we need to find closing curly bracket and treat the whole block + // as one, skip tags inside if there any + if (substr($tokens[$last]['content'], -1) === '{') { + $dep = 1; + $i = $last; + $max = $tokens[$commentStart]['comment_closer']; + while ($dep > 0 && $i < $max) { + $i = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $i + 1, $max); + + if (! $i) { + break; + } + + if ($tokens[$i]['content'][0] === '}') { + --$dep; + } + + if (substr($tokens[$i]['content'], -1) === '{') { + ++$dep; + } + } + + if ($dep > 0) { + $error = 'Tag contains nested description, but cannot find the closing bracket'; + $phpcsFile->addError($error, $last, 'NotClosed'); + return; + } + + $last = $i; + while (isset($tags[$key + 1]) && $tags[$key + 1] < $i) { + next($tags); + ++$key; + } + } + while ($tokens[$last + 1]['line'] === $tokens[$last]['line']) { ++$last; } $data[] = [ - 'tag' => strtolower($tokens[$tag]['content']), + 'tag' => strtolower($tokens[$tag]['content']), 'token' => $tag, 'first' => $phpcsFile->findFirstOnLine([], $tag, true), - 'last' => $last, + 'last' => $last, ]; + + next($tags); } $firstTag = current($data); diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc b/test/Sniffs/Commenting/DocCommentUnitTest.inc index 3296bca9..0fd7dd36 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc @@ -195,4 +195,17 @@ class Foo public function test9() { } + + /** + * @param array $arr { + * @var bool $required Here is the description + * of the field in the array + * hey + * @var string $name Another very long + * description here + * } + */ + public function test10(array $arr) + { + } } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed index c56fe5bb..879f5b9a 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed @@ -197,4 +197,17 @@ $c = 'xyz'; public function test9() { } + + /** + * @param array $arr { + * @var bool $required Here is the description + * of the field in the array + * hey + * @var string $name Another very long + * description here + * } + */ + public function test10(array $arr) + { + } } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.php b/test/Sniffs/Commenting/DocCommentUnitTest.php index d5c225c8..cd4db420 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.php +++ b/test/Sniffs/Commenting/DocCommentUnitTest.php @@ -155,6 +155,7 @@ public function getErrorList($testFile = '') 184 => 1, 185 => 1, 192 => 1, + 203 => 1, ]; } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc index 088e5b1e..7ca8d629 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc @@ -52,4 +52,16 @@ class Foo * @param string $a */ private function toManyEmptyLines($a) {} + + /** + * @return array { + * @var bool $foo + * @var float $bar + * } + * @param array $a { + * @var string $isCache + * @var string $template + * } + */ + private function longParams($a) {} } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed index 84daf65b..ad647f2e 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed @@ -48,4 +48,16 @@ class Foo * @param string $a */ private function toManyEmptyLines($a) {} + + /** + * @param array $a { + * @var string $isCache + * @var string $template + * } + * @return array { + * @var bool $foo + * @var float $bar + * } + */ + private function longParams($a) {} } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.php b/test/Sniffs/Commenting/FunctionCommentUnitTest.php index 16496b29..37d2fcde 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.php +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.php @@ -21,6 +21,7 @@ public function getErrorList($testFile = '') 39 => 1, 42 => 1, 49 => 1, + 57 => 1, ]; } diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.3.inc b/test/Sniffs/Functions/ReturnTypeUnitTest.3.inc index a7a5e87f..6c694769 100644 --- a/test/Sniffs/Functions/ReturnTypeUnitTest.3.inc +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.3.inc @@ -211,4 +211,15 @@ class FunctionCommentReturn { return $x; } + + /** + * @return array { + * @var bool $required Weather this element is required + * @var string $label The display name for this element + * } + */ + public function test27() : array + { + return []; + } } From 832088189f3281af20965cf2b9b75fa4da08e98d Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 14 Feb 2018 08:34:25 +0000 Subject: [PATCH 165/225] Updated to PHP 7.1 - updated Travis CI configuration - required in composer.json - added strict types declaration --- .travis.yml | 23 +------------------ composer.json | 3 ++- composer.lock | 6 +++-- src/ZendCodingStandard/CodingStandard.php | 3 +++ src/ZendCodingStandard/Helper/Methods.php | 3 +++ src/ZendCodingStandard/Helper/Namespaces.php | 3 +++ .../Sniffs/Arrays/FormatSniff.php | 3 +++ .../Sniffs/Arrays/TrailingArrayCommaSniff.php | 2 ++ .../AlphabeticallySortedTraitsSniff.php | 3 +++ .../Sniffs/Classes/NoNullValuesSniff.php | 3 +++ .../Sniffs/Classes/TraitUsageSniff.php | 3 +++ .../Sniffs/Commenting/DocCommentSniff.php | 3 +++ .../Commenting/FunctionCommentSniff.php | 2 ++ .../FunctionDataProviderTagSniff.php | 3 +++ .../Commenting/FunctionDisallowedTagSniff.php | 3 +++ .../NoInlineCommentAfterCurlyCloseSniff.php | 3 +++ .../Sniffs/Commenting/TagCaseSniff.php | 3 +++ .../Commenting/VariableCommentSniff.php | 2 ++ .../Sniffs/Formatting/DoubleColonSniff.php | 3 +++ .../Sniffs/Formatting/NewKeywordSniff.php | 3 +++ .../Formatting/NoSpaceAfterSplatSniff.php | 3 +++ .../Sniffs/Formatting/ReferenceSniff.php | 3 +++ .../Sniffs/Formatting/ReturnTypeSniff.php | 3 +++ .../UnnecessaryParenthesesSniff.php | 3 +++ .../Sniffs/Functions/ParamSniff.php | 3 +++ .../Sniffs/Functions/ReturnTypeSniff.php | 3 +++ .../Sniffs/Functions/ThrowsSniff.php | 3 +++ .../Sniffs/Methods/LineAfterSniff.php | 3 +++ .../AlphabeticallySortedUsesSniff.php | 3 +++ .../ConstAndFunctionKeywordsSniff.php | 3 +++ .../Namespaces/UnusedUseStatementSniff.php | 2 ++ .../UseDoesNotStartWithBackslashSniff.php | 3 +++ .../ValidVariableNameSniff.php | 2 ++ .../Sniffs/Operators/BooleanOperatorSniff.php | 3 +++ .../Sniffs/Operators/TernaryOperatorSniff.php | 3 +++ .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 3 +++ .../PHP/ImportInternalConstantSniff.php | 3 +++ .../PHP/ImportInternalFunctionSniff.php | 3 +++ .../PHP/InstantiatingParenthesisSniff.php | 3 +++ .../Sniffs/PHP/LowerCaseKeywordSniff.php | 3 +++ .../Sniffs/PHP/RedundantSemicolonSniff.php | 3 +++ .../Sniffs/PHP/TypeCastingSniff.php | 3 +++ .../Strings/NoConcatenationAtTheEndSniff.php | 3 +++ .../Sniffs/WhiteSpace/BlankLineSniff.php | 3 +++ .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 2 ++ .../WhiteSpace/NoBlankLineAtStartSniff.php | 3 +++ .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 3 +++ test/Ruleset.php | 3 +++ test/Sniffs/Arrays/FormatUnitTest.php | 3 +++ .../Arrays/TrailingArrayCommaUnitTest.php | 3 +++ .../AlphabeticallySortedTraitsUnitTest.php | 3 +++ test/Sniffs/Classes/NoNullValuesUnitTest.php | 3 +++ test/Sniffs/Classes/TraitUsageUnitTest.php | 3 +++ test/Sniffs/Commenting/DocCommentUnitTest.php | 3 +++ .../Commenting/FunctionCommentUnitTest.php | 3 +++ .../FunctionDataProviderTagUnitTest.php | 3 +++ .../FunctionDisallowedTagUnitTest.php | 3 +++ ...NoInlineCommentAfterCurlyCloseUnitTest.php | 3 +++ test/Sniffs/Commenting/TagCaseUnitTest.php | 3 +++ .../Sniffs/Formatting/DoubleColonUnitTest.php | 3 +++ test/Sniffs/Formatting/NewKeywordUnitTest.php | 3 +++ .../Formatting/NoSpaceAfterSplatUnitTest.php | 3 +++ test/Sniffs/Formatting/ReferenceUnitTest.php | 3 +++ test/Sniffs/Formatting/ReturnTypeUnitTest.php | 3 +++ .../UnnecessaryParenthesesUnitTest.php | 3 +++ test/Sniffs/Functions/ParamUnitTest.php | 3 +++ test/Sniffs/Functions/ReturnTypeUnitTest.php | 3 +++ test/Sniffs/Functions/ThrowsUnitTest.php | 3 +++ test/Sniffs/Methods/LineAfterUnitTest.php | 3 +++ .../AlphabeticallySortedUsesUnitTest.php | 3 +++ .../ConstAndFunctionKeywordsUnitTest.php | 3 +++ .../Namespaces/UnusedUseStatementUnitTest.php | 3 +++ .../UseDoesNotStartWithBackslashUnitTest.php | 3 +++ .../ValidVariableNameUnitTest.php | 3 +++ .../Operators/BooleanOperatorUnitTest.php | 3 +++ .../Operators/TernaryOperatorUnitTest.php | 3 +++ .../PHP/CorrectClassNameCaseUnitTest.php | 3 +++ .../PHP/ImportInternalConstantUnitTest.php | 3 +++ .../PHP/ImportInternalFunctionUnitTest.php | 3 +++ .../PHP/InstantiatingParenthesisUnitTest.php | 3 +++ test/Sniffs/PHP/LowerCaseKeywordUnitTest.php | 3 +++ .../Sniffs/PHP/RedundantSemicolonUnitTest.php | 3 +++ test/Sniffs/PHP/TypeCastingUnitTest.php | 3 +++ .../NoConcatenationAtTheEndUnitTest.php | 3 +++ test/Sniffs/TestCase.php | 3 +++ test/Sniffs/WhiteSpace/BlankLineUnitTest.php | 3 +++ .../WhiteSpace/CommaSpacingUnitTest.php | 3 +++ .../WhiteSpace/NoBlankLineAtStartUnitTest.php | 3 +++ .../Sniffs/WhiteSpace/ScopeIndentUnitTest.php | 3 +++ 89 files changed, 259 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index f518cc12..1aeaccab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,26 +13,6 @@ env: matrix: include: - - php: 5.6 - env: - - DEPS=lowest - - php: 5.6 - env: - - DEPS=locked - - LEGACY_DEPS="doctrine/instantiator phpunit/phpunit" - - php: 5.6 - env: - - DEPS=latest - - php: 7 - env: - - DEPS=lowest - - php: 7 - env: - - DEPS=locked - - LEGACY_DEPS="doctrine/instantiator phpunit/phpunit" - - php: 7 - env: - - DEPS=latest - php: 7.1 env: - DEPS=lowest @@ -58,8 +38,7 @@ before_install: - if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi install: - - travis_retry composer install $COMPOSER_ARGS --ignore-platform-reqs - - if [[ $LEGACY_DEPS != '' ]]; then travis_retry composer update $COMPOSER_ARGS --with-dependencies $LEGACY_DEPS ; fi + - travis_retry composer install $COMPOSER_ARGS - if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-lowest --prefer-stable $COMPOSER_ARGS ; fi - if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $COVERAGE_DEPS ; fi diff --git a/composer.json b/composer.json index 943ae69d..0574ec4d 100644 --- a/composer.json +++ b/composer.json @@ -8,10 +8,11 @@ "coding standard" ], "require": { + "php": "^7.1", "squizlabs/php_codesniffer": "3.2.2" }, "require-dev": { - "phpunit/phpunit": "^5.7.27 || ^6.5.6 || ^7.0.1" + "phpunit/phpunit": "^7.0.1" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 7f94066d..5382a836 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "19e18b2f9302005e2361fd387727905e", + "content-hash": "2379eab2896b6b8a22ce5e31fb6ae184", "packages": [ { "name": "squizlabs/php_codesniffer", @@ -1519,6 +1519,8 @@ "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": [], + "platform": { + "php": "^7.1" + }, "platform-dev": [] } diff --git a/src/ZendCodingStandard/CodingStandard.php b/src/ZendCodingStandard/CodingStandard.php index a8486ee5..a6a5457b 100644 --- a/src/ZendCodingStandard/CodingStandard.php +++ b/src/ZendCodingStandard/CodingStandard.php @@ -1,4 +1,7 @@ Date: Wed, 14 Feb 2018 10:52:13 +0000 Subject: [PATCH 166/225] Removed extension of Generic.PHP.LowerCaseKeyword as all fixes are merged --- .../Sniffs/PHP/LowerCaseKeywordSniff.php | 33 --------- src/ZendCodingStandard/ruleset.xml | 3 +- test/Sniffs/PHP/LowerCaseKeywordUnitTest.inc | 68 ------------------ .../PHP/LowerCaseKeywordUnitTest.inc.fixed | 68 ------------------ test/Sniffs/PHP/LowerCaseKeywordUnitTest.php | 69 ------------------- 5 files changed, 1 insertion(+), 240 deletions(-) delete mode 100644 src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php delete mode 100644 test/Sniffs/PHP/LowerCaseKeywordUnitTest.inc delete mode 100644 test/Sniffs/PHP/LowerCaseKeywordUnitTest.inc.fixed delete mode 100644 test/Sniffs/PHP/LowerCaseKeywordUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php b/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php deleted file mode 100644 index 74708e55..00000000 --- a/src/ZendCodingStandard/Sniffs/PHP/LowerCaseKeywordSniff.php +++ /dev/null @@ -1,33 +0,0 @@ - - - + diff --git a/test/Sniffs/PHP/LowerCaseKeywordUnitTest.inc b/test/Sniffs/PHP/LowerCaseKeywordUnitTest.inc deleted file mode 100644 index 1e136302..00000000 --- a/test/Sniffs/PHP/LowerCaseKeywordUnitTest.inc +++ /dev/null @@ -1,68 +0,0 @@ - $b; - } - - FINAL PUBLIC FUNCTION finalMethod() - { - SWITCH (1) { - CASE 0: - RETURN FUNCTION () {}; - DEFAULT: - BREAK; - } - } -} diff --git a/test/Sniffs/PHP/LowerCaseKeywordUnitTest.inc.fixed b/test/Sniffs/PHP/LowerCaseKeywordUnitTest.inc.fixed deleted file mode 100644 index cf604c8b..00000000 --- a/test/Sniffs/PHP/LowerCaseKeywordUnitTest.inc.fixed +++ /dev/null @@ -1,68 +0,0 @@ - $b; - } - - final public function finalMethod() - { - switch (1) { - case 0: - return function () {}; - default: - break; - } - } -} diff --git a/test/Sniffs/PHP/LowerCaseKeywordUnitTest.php b/test/Sniffs/PHP/LowerCaseKeywordUnitTest.php deleted file mode 100644 index 3ed3cb9c..00000000 --- a/test/Sniffs/PHP/LowerCaseKeywordUnitTest.php +++ /dev/null @@ -1,69 +0,0 @@ - 1, - 5 => 1, - 7 => 2, - 8 => 1, - 9 => 1, - 11 => 1, - 13 => 3, - 15 => 1, - 16 => 1, - 17 => 2, - 18 => 2, - 20 => 1, - 21 => 1, - 23 => 3, - 24 => 4, - 25 => 1, - 29 => 3, - 31 => 3, - 33 => 1, - 36 => 1, - 37 => 1, - 39 => 1, - 40 => 1, - 43 => 1, - 44 => 1, - 45 => 1, - 46 => 1, - 47 => 1, - 48 => 1, - 49 => 2, - 52 => 1, - 53 => 2, - 55 => 1, - 56 => 1, - 59 => 3, - 61 => 1, - 62 => 1, - 63 => 2, - 64 => 1, - 65 => 1, - ]; - } - - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') - { - return []; - } -} From c84b2979f68caa48b28b0bde4819aa4720aa6ff5 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 14 Feb 2018 10:54:31 +0000 Subject: [PATCH 167/225] Fixed replacing 'non-string' type hints The following type hints do not have T_STRING type: - array -> T_ARRAY_HINT - callable -> T_CALLABLE --- src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php | 6 ++++-- test/Sniffs/Functions/ParamUnitTest.inc | 2 ++ test/Sniffs/Functions/ParamUnitTest.inc.fixed | 2 ++ test/Sniffs/Functions/ParamUnitTest.php | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php index 9b7c469c..926ff7b4 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php @@ -30,6 +30,8 @@ use function ucfirst; use function usort; +use const T_ARRAY_HINT; +use const T_CALLABLE; use const T_DOC_COMMENT_STAR; use const T_DOC_COMMENT_STRING; use const T_DOC_COMMENT_WHITESPACE; @@ -250,8 +252,8 @@ private function fixParamOrder(File $phpcsFile, array $map, $wrong) */ private function replaceParamTypeHint(File $phpcsFile, $varPtr, $newTypeHint) { - $last = $phpcsFile->findPrevious(T_STRING, $varPtr - 1); - $first = $phpcsFile->findPrevious([T_NULLABLE, T_STRING, T_NS_SEPARATOR], $last, null, true); + $last = $phpcsFile->findPrevious([T_ARRAY_HINT, T_CALLABLE, T_STRING], $varPtr - 1); + $first = $phpcsFile->findPrevious([T_NULLABLE, T_STRING, T_NS_SEPARATOR], $last - 1, null, true); $phpcsFile->fixer->beginChangeset(); $phpcsFile->fixer->replaceToken($last, $newTypeHint); diff --git a/test/Sniffs/Functions/ParamUnitTest.inc b/test/Sniffs/Functions/ParamUnitTest.inc index 9b8fa581..eb3fea23 100644 --- a/test/Sniffs/Functions/ParamUnitTest.inc +++ b/test/Sniffs/Functions/ParamUnitTest.inc @@ -308,4 +308,6 @@ class FunctionParam extends FunctionParamParent * @param \Generator $a */ public function generatorDoesNotNeedSpecificationInDocs($a) {} + + private function privateMethod(CALLABLE $o, Array $p) {} } diff --git a/test/Sniffs/Functions/ParamUnitTest.inc.fixed b/test/Sniffs/Functions/ParamUnitTest.inc.fixed index 9207ea26..fb352994 100644 --- a/test/Sniffs/Functions/ParamUnitTest.inc.fixed +++ b/test/Sniffs/Functions/ParamUnitTest.inc.fixed @@ -308,4 +308,6 @@ class FunctionParam extends FunctionParamParent * @param \Generator $a */ public function generatorDoesNotNeedSpecificationInDocs($a) {} + + private function privateMethod(callable $o, array $p) {} } diff --git a/test/Sniffs/Functions/ParamUnitTest.php b/test/Sniffs/Functions/ParamUnitTest.php index cc89c4a0..df1c8f9d 100644 --- a/test/Sniffs/Functions/ParamUnitTest.php +++ b/test/Sniffs/Functions/ParamUnitTest.php @@ -103,6 +103,7 @@ public function getErrorList($testFile = '') 282 => 1, 296 => 1, 301 => 1, + 312 => 2, ]; } From 48084182f51194b1d72a0fe24afacc1f165ac372 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 14 Feb 2018 11:01:49 +0000 Subject: [PATCH 168/225] PHP 7.1 features - added type hints - added return types - null coalescing operator --- src/ZendCodingStandard/CodingStandard.php | 15 +--- src/ZendCodingStandard/Helper/Methods.php | 54 +++------------ src/ZendCodingStandard/Helper/Namespaces.php | 17 ++--- .../Sniffs/Arrays/FormatSniff.php | 12 +--- .../Sniffs/Arrays/TrailingArrayCommaSniff.php | 2 +- .../AlphabeticallySortedTraitsSniff.php | 22 ++---- .../Sniffs/Classes/NoNullValuesSniff.php | 6 +- .../Sniffs/Classes/TraitUsageSniff.php | 19 ++---- .../Sniffs/Commenting/DocCommentSniff.php | 68 +++++-------------- .../Commenting/FunctionCommentSniff.php | 13 +--- .../FunctionDataProviderTagSniff.php | 2 +- .../Commenting/FunctionDisallowedTagSniff.php | 2 +- .../NoInlineCommentAfterCurlyCloseSniff.php | 2 +- .../Sniffs/Commenting/TagCaseSniff.php | 2 +- .../Commenting/VariableCommentSniff.php | 6 +- .../Sniffs/Formatting/DoubleColonSniff.php | 2 +- .../Sniffs/Formatting/NewKeywordSniff.php | 2 +- .../Formatting/NoSpaceAfterSplatSniff.php | 2 +- .../Sniffs/Formatting/ReferenceSniff.php | 2 +- .../Sniffs/Formatting/ReturnTypeSniff.php | 14 ++-- .../UnnecessaryParenthesesSniff.php | 9 +-- .../Sniffs/Functions/ParamSniff.php | 44 ++++-------- .../Sniffs/Functions/ReturnTypeSniff.php | 39 +++-------- .../Sniffs/Functions/ThrowsSniff.php | 19 ++---- .../Sniffs/Methods/LineAfterSniff.php | 4 +- .../AlphabeticallySortedUsesSniff.php | 16 ++--- .../ConstAndFunctionKeywordsSniff.php | 2 +- .../Namespaces/UnusedUseStatementSniff.php | 2 +- .../UseDoesNotStartWithBackslashSniff.php | 2 +- .../ValidVariableNameSniff.php | 10 ++- .../Sniffs/Operators/BooleanOperatorSniff.php | 2 +- .../Sniffs/Operators/TernaryOperatorSniff.php | 14 +--- .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 64 +++++------------ .../PHP/ImportInternalConstantSniff.php | 8 +-- .../PHP/ImportInternalFunctionSniff.php | 8 +-- .../PHP/InstantiatingParenthesisSniff.php | 2 +- .../Sniffs/PHP/RedundantSemicolonSniff.php | 2 +- .../Sniffs/PHP/TypeCastingSniff.php | 4 +- .../Strings/NoConcatenationAtTheEndSniff.php | 2 +- .../Sniffs/WhiteSpace/BlankLineSniff.php | 2 +- .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 2 +- .../WhiteSpace/NoBlankLineAtStartSniff.php | 2 +- .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 26 ++----- 43 files changed, 153 insertions(+), 396 deletions(-) diff --git a/src/ZendCodingStandard/CodingStandard.php b/src/ZendCodingStandard/CodingStandard.php index a6a5457b..e1919fd4 100644 --- a/src/ZendCodingStandard/CodingStandard.php +++ b/src/ZendCodingStandard/CodingStandard.php @@ -27,9 +27,8 @@ class CodingStandard * Returns the correct type name suggestion if type name is invalid. * * @param string $varType The variable type to process. - * @return string */ - public static function suggestType($varType) + public static function suggestType(string $varType) : string { $lowerVarType = strtolower($varType); switch ($lowerVarType) { @@ -78,11 +77,7 @@ public static function suggestType($varType) return Common::suggestType($varType); } - /** - * @param int $stackPtr - * @return bool - */ - public static function isTraitUse(File $phpcsFile, $stackPtr) + public static function isTraitUse(File $phpcsFile, int $stackPtr) : bool { $tokens = $phpcsFile->getTokens(); @@ -100,11 +95,7 @@ public static function isTraitUse(File $phpcsFile, $stackPtr) return true; } - /** - * @param int $stackPtr - * @return bool - */ - public static function isGlobalUse(File $phpcsFile, $stackPtr) + public static function isGlobalUse(File $phpcsFile, int $stackPtr) : bool { $tokens = $phpcsFile->getTokens(); diff --git a/src/ZendCodingStandard/Helper/Methods.php b/src/ZendCodingStandard/Helper/Methods.php index eff867af..956e1318 100644 --- a/src/ZendCodingStandard/Helper/Methods.php +++ b/src/ZendCodingStandard/Helper/Methods.php @@ -127,10 +127,7 @@ trait Methods 'void', ]; - /** - * @param int $stackPtr - */ - private function initScope(File $phpcsFile, $stackPtr) + private function initScope(File $phpcsFile, int $stackPtr) : void { if ($this->currentFile !== $phpcsFile) { $this->currentFile = $phpcsFile; @@ -163,12 +160,7 @@ private function initScope(File $phpcsFile, $stackPtr) } } - /** - * @param string $a - * @param string $b - * @return int - */ - public function sortTypes($a, $b) + public function sortTypes(string $a, string $b) : int { $a = strtolower(str_replace('\\', ':', $a)); $b = strtolower(str_replace('\\', ':', $b)); @@ -214,11 +206,7 @@ public function sortTypes($a, $b) ); } - /** - * @param string $class - * @return string - */ - private function getSuggestedType($class) + private function getSuggestedType(string $class) : string { $prefix = $class[0] === '?' ? '?' : ''; $suffix = strstr($class, '['); @@ -260,12 +248,7 @@ private function getSuggestedType($class) return $class; } - /** - * @param string $typeHint - * @param string $typeStr - * @return bool - */ - private function typesMatch($typeHint, $typeStr) + private function typesMatch(string $typeHint, string $typeStr) : bool { $isNullable = $typeHint[0] === '?'; $lowerTypeHint = strtolower($isNullable ? substr($typeHint, 1) : $typeHint); @@ -300,11 +283,7 @@ private function typesMatch($typeHint, $typeStr) || $fqcnTypeHint . '|null' === $fqcnTypes)); } - /** - * @param string $class - * @return string - */ - private function getFQCN($class) + private function getFQCN(string $class) : string { // It is a simple type if (in_array(strtolower($class), $this->simpleReturnTypes, true)) { @@ -325,11 +304,7 @@ private function getFQCN($class) return ($this->currentNamespace ? '\\' . $this->currentNamespace : '') . '\\' . $class; } - /** - * @param string $name - * @return bool - */ - private function isClassName($name) + private function isClassName(string $name) : bool { if (! $this->className) { return false; @@ -344,11 +319,7 @@ private function isClassName($name) || $lower === $lowerClassName; } - /** - * @param string $name - * @return bool - */ - private function isParentClassName($name) + private function isParentClassName(string $name) : bool { if (! $this->parentClassName) { return false; @@ -362,10 +333,7 @@ private function isParentClassName($name) || $lower === $lowerParentClassName; } - /** - * @param int $tagPtr - */ - private function removeTag(File $phpcsFile, $tagPtr) + private function removeTag(File $phpcsFile, int $tagPtr) : void { $tokens = $phpcsFile->getTokens(); @@ -382,11 +350,7 @@ private function removeTag(File $phpcsFile, $tagPtr) $phpcsFile->fixer->endChangeset(); } - /** - * @param int $stackPtr - * @return null|int - */ - private function getCommentStart(File $phpcsFile, $stackPtr) + private function getCommentStart(File $phpcsFile, int $stackPtr) : ?int { $tokens = $phpcsFile->getTokens(); $skip = Tokens::$methodPrefixes diff --git a/src/ZendCodingStandard/Helper/Namespaces.php b/src/ZendCodingStandard/Helper/Namespaces.php index b27aa856..ef9e6029 100644 --- a/src/ZendCodingStandard/Helper/Namespaces.php +++ b/src/ZendCodingStandard/Helper/Namespaces.php @@ -28,11 +28,7 @@ */ trait Namespaces { - /** - * @param int $stackPtr - * @return string - */ - private function getNamespace(File $phpcsFile, $stackPtr) + private function getNamespace(File $phpcsFile, int $stackPtr) : string { if ($nsStart = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr - 1)) { $nsEnd = $phpcsFile->findNext([T_NS_SEPARATOR, T_STRING, T_WHITESPACE], $nsStart + 1, null, true); @@ -45,10 +41,9 @@ private function getNamespace(File $phpcsFile, $stackPtr) /** * Returns array of imported classes. Key is lowercase name, and value is FQCN. * - * @param int $stackPtr * @return string[][] */ - private function getGlobalUses(File $phpcsFile, $stackPtr = 0) + private function getGlobalUses(File $phpcsFile, int $stackPtr = 0) : array { $first = 0; $last = $phpcsFile->numTokens; @@ -98,11 +93,9 @@ private function getGlobalUses(File $phpcsFile, $stackPtr = 0) } /** - * @param int $stackPtr - * @param null|int $lastUse * @return string[][] */ - private function getImportedConstants(File $phpcsFile, $stackPtr, &$lastUse) + private function getImportedConstants(File $phpcsFile, int $stackPtr, ?int &$lastUse) : array { $first = 0; $last = $phpcsFile->numTokens; @@ -152,11 +145,9 @@ private function getImportedConstants(File $phpcsFile, $stackPtr, &$lastUse) } /** - * @param int $stackPtr - * @param null|int $lastUse * @return string[][] */ - private function getImportedFunctions(File $phpcsFile, $stackPtr, &$lastUse) + private function getImportedFunctions(File $phpcsFile, int $stackPtr, ?int &$lastUse) : array { $first = 0; $last = $phpcsFile->numTokens; diff --git a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index 1ee22155..fa5aad28 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -29,7 +29,7 @@ class FormatSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_OPEN_SHORT_ARRAY]; } @@ -53,10 +53,7 @@ public function process(File $phpcsFile, $stackPtr) $this->singleLineArray($phpcsFile, $stackPtr); } - /** - * @param int $stackPtr - */ - private function multiLineArray(File $phpcsFile, $stackPtr) + private function multiLineArray(File $phpcsFile, int $stackPtr) : void { $tokens = $phpcsFile->getTokens(); $arrayToken = $tokens[$stackPtr]; @@ -164,10 +161,7 @@ private function multiLineArray(File $phpcsFile, $stackPtr) } } - /** - * @param int $stackPtr - */ - private function singleLineArray(File $phpcsFile, $stackPtr) + private function singleLineArray(File $phpcsFile, int $stackPtr) : void { $tokens = $phpcsFile->getTokens(); $arrayToken = $tokens[$stackPtr]; diff --git a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php index d698e4b6..21fb599d 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php @@ -28,7 +28,7 @@ class TrailingArrayCommaSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_OPEN_SHORT_ARRAY]; } diff --git a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php index 3f261513..ba62254b 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php @@ -31,7 +31,7 @@ class AlphabeticallySortedTraitsSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_CLASS, T_TRAIT, T_ANON_CLASS]; } @@ -69,10 +69,9 @@ public function process(File $phpcsFile, $stackPtr) } /** - * @param int $scopePtr * @return string[][] */ - private function getTraits(File $phpcsFile, $scopePtr) + private function getTraits(File $phpcsFile, int $scopePtr) : array { $tokens = $phpcsFile->getTokens(); @@ -111,11 +110,7 @@ private function getTraits(File $phpcsFile, $scopePtr) return $uses; } - /** - * @param int $stackPtr - * @return int - */ - private function getEndOfTraitScope(File $phpcsFile, $stackPtr) + private function getEndOfTraitScope(File $phpcsFile, int $stackPtr) : int { $tokens = $phpcsFile->getTokens(); @@ -133,9 +128,8 @@ private function getEndOfTraitScope(File $phpcsFile, $stackPtr) /** * @param string[] $a * @param string[] $b - * @return int */ - private function compareUseStatements(array $a, array $b) + private function compareUseStatements(array $a, array $b) : int { return strcasecmp( $this->clearName($a['name']), @@ -143,11 +137,7 @@ private function compareUseStatements(array $a, array $b) ); } - /** - * @param string $name - * @return string - */ - private function clearName($name) + private function clearName(string $name) : string { return str_replace('\\', ':', $name); } @@ -155,7 +145,7 @@ private function clearName($name) /** * @param string[][] $uses */ - private function fixAlphabeticalOrder(File $phpcsFile, array $uses) + private function fixAlphabeticalOrder(File $phpcsFile, array $uses) : void { $first = reset($uses); $last = end($uses); diff --git a/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php b/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php index 3e8552d3..0c3d1590 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/NoNullValuesSniff.php @@ -19,7 +19,7 @@ class NoNullValuesSniff extends AbstractVariableSniff /** * @param int $stackPtr */ - protected function processMemberVar(File $phpcsFile, $stackPtr) + protected function processMemberVar(File $phpcsFile, $stackPtr) : void { $tokens = $phpcsFile->getTokens(); @@ -50,7 +50,7 @@ protected function processMemberVar(File $phpcsFile, $stackPtr) /** * @param int $stackPtr */ - protected function processVariable(File $phpcsFile, $stackPtr) + protected function processVariable(File $phpcsFile, $stackPtr) : void { // Normal variables are not processed in this sniff. } @@ -58,7 +58,7 @@ protected function processVariable(File $phpcsFile, $stackPtr) /** * @param int $stackPtr */ - protected function processVariableInString(File $phpcsFile, $stackPtr) + protected function processVariableInString(File $phpcsFile, $stackPtr) : void { // Variables in string are not processed in this sniff. } diff --git a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php index 432aa27c..9394603d 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php @@ -30,7 +30,7 @@ class TraitUsageSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_USE]; } @@ -280,7 +280,7 @@ public function process(File $phpcsFile, $stackPtr) * * @param string[] $statements */ - private function fixAlphabeticalOrder(File $phpcsFile, array $statements) + private function fixAlphabeticalOrder(File $phpcsFile, array $statements) : void { $phpcsFile->fixer->beginChangeset(); foreach ($statements as $statement) { @@ -289,7 +289,9 @@ private function fixAlphabeticalOrder(File $phpcsFile, array $statements) } } - usort($statements, [$this, 'compareStatements']); + usort($statements, function (array $a, array $b) { + return $this->compareStatements($a, $b); + }); $begins = array_column($statements, 'begin'); sort($begins); @@ -302,13 +304,10 @@ private function fixAlphabeticalOrder(File $phpcsFile, array $statements) } /** - * @internal - * * @param string[] $a * @param string[] $b - * @return int */ - public function compareStatements(array $a, array $b) + private function compareStatements(array $a, array $b) : int { return strcasecmp( $this->clearName($a['content']), @@ -316,11 +315,7 @@ public function compareStatements(array $a, array $b) ); } - /** - * @param string $name - * @return string - */ - private function clearName($name) + private function clearName(string $name) : string { return str_replace('\\', ':', $name); } diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index dbf5d774..f259db00 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -54,7 +54,7 @@ class DocCommentSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_DOC_COMMENT_OPEN_TAG]; } @@ -78,7 +78,7 @@ public function process(File $phpcsFile, $stackPtr) $this->checkTagsSpaces($phpcsFile, $commentStart); // Doc block comment in one line. - if ($tokens[$commentStart]['line'] == $tokens[$commentEnd]['line']) { + if ($tokens[$commentStart]['line'] === $tokens[$commentEnd]['line']) { $this->checkSpacesInOneLineComment($phpcsFile, $commentStart, $commentEnd); return; @@ -95,12 +95,8 @@ public function process(File $phpcsFile, $stackPtr) /** * Checks if doc comment is empty. - * - * @param int $commentStart - * @param int $commentEnd - * @return bool */ - private function checkIfEmpty(File $phpcsFile, $commentStart, $commentEnd) + private function checkIfEmpty(File $phpcsFile, int $commentStart, int $commentEnd) : bool { $tokens = $phpcsFile->getTokens(); @@ -160,10 +156,8 @@ private function checkIfEmpty(File $phpcsFile, $commentStart, $commentEnd) /** * Checks if there is no any other content before doc comment opening tag, * and if there is blank line before doc comment (for multiline doc comment). - * - * @param int $commentStart */ - private function checkBeforeOpen(File $phpcsFile, $commentStart) + private function checkBeforeOpen(File $phpcsFile, int $commentStart) : void { $tokens = $phpcsFile->getTokens(); @@ -198,10 +192,8 @@ private function checkBeforeOpen(File $phpcsFile, $commentStart) /** * Checks if there is no any other content after doc comment opening tag (for multiline doc comment). - * - * @param int $commentStart */ - private function checkAfterOpen(File $phpcsFile, $commentStart) + private function checkAfterOpen(File $phpcsFile, int $commentStart) : void { $tokens = $phpcsFile->getTokens(); @@ -235,10 +227,8 @@ private function checkAfterOpen(File $phpcsFile, $commentStart) /** * Checks if there is no any other content before doc comment closing tag (for multiline doc comment). - * - * @param int $commentEnd */ - private function checkBeforeClose(File $phpcsFile, $commentEnd) + private function checkBeforeClose(File $phpcsFile, int $commentEnd) : void { $tokens = $phpcsFile->getTokens(); @@ -261,11 +251,8 @@ private function checkBeforeClose(File $phpcsFile, $commentEnd) /** * Checks if there is no any other content after doc comment closing tag (for multiline doc comment). - * - * @param int $commentStart - * @param int $commentEnd */ - private function checkAfterClose(File $phpcsFile, $commentStart, $commentEnd) + private function checkAfterClose(File $phpcsFile, int $commentStart, int $commentEnd) : void { $tokens = $phpcsFile->getTokens(); @@ -329,11 +316,8 @@ private function checkAfterClose(File $phpcsFile, $commentStart, $commentEnd) /** * Checks if there is exactly one space after doc comment opening tag, * and exactly one space before closing tag (for single line doc comment). - * - * @param int $commentStart - * @param int $commentEnd */ - private function checkSpacesInOneLineComment(File $phpcsFile, $commentStart, $commentEnd) + private function checkSpacesInOneLineComment(File $phpcsFile, int $commentStart, int $commentEnd) : void { $tokens = $phpcsFile->getTokens(); @@ -373,17 +357,11 @@ private function checkSpacesInOneLineComment(File $phpcsFile, $commentStart, $co * More than one space is allowed, unless the line contains tag. * * @todo: needs to check with doctrine annotations - * - * @param int $commentStart - * @param int $commentEnd */ - private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEnd) + private function checkSpacesAfterStar(File $phpcsFile, int $commentStart, int $commentEnd) : void { $tokens = $phpcsFile->getTokens(); - - $firstTag = isset($tokens[$commentStart]['comment_tags'][0]) - ? $tokens[$commentStart]['comment_tags'][0] - : null; + $firstTag = $tokens[$commentStart]['comment_tags'][0] ?? null; $next = $commentStart; $search = [T_DOC_COMMENT_STAR, T_DOC_COMMENT_CLOSE_TAG]; @@ -472,7 +450,7 @@ private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEn if ($tokens[$prev2]['line'] === $tokens[$next]['line'] - 1) { if ($tokens[$prev]['line'] !== $tokens[$next + 1]['line'] - 1) { - $expectedSpaces = 1 + max( + $expectedSpaces = 1 + (int) max( round(($spaces - 1) / $this->indent) * $this->indent, $this->indent ); @@ -502,11 +480,8 @@ private function checkSpacesAfterStar(File $phpcsFile, $commentStart, $commentEn /** * Doc comment cannot have empty line on the beginning of the comment, at the end of the comment, * and there is allowed only one empty line between two comment sections. - * - * @param int $commentStart - * @param int $commentEnd */ - private function checkBlankLinesInComment(File $phpcsFile, $commentStart, $commentEnd) + private function checkBlankLinesInComment(File $phpcsFile, int $commentStart, int $commentEnd) : void { $tokens = $phpcsFile->getTokens(); @@ -605,11 +580,8 @@ private function checkBlankLinesInComment(File $phpcsFile, $commentStart, $comme /** * Checks indents of the comment (opening tag, lines with star, closing tag). - * - * @param int $commentStart - * @param int $commentEnd */ - private function checkCommentIndents(File $phpcsFile, $commentStart, $commentEnd) + private function checkCommentIndents(File $phpcsFile, int $commentStart, int $commentEnd) : void { $tokens = $phpcsFile->getTokens(); @@ -723,10 +695,8 @@ private function checkCommentIndents(File $phpcsFile, $commentStart, $commentEnd /** * Check if there is one blank line before comment tags. - * - * @param int $commentStart */ - private function checkBlankLineBeforeTags(File $phpcsFile, $commentStart) + private function checkBlankLineBeforeTags(File $phpcsFile, int $commentStart) : void { $tokens = $phpcsFile->getTokens(); @@ -759,10 +729,7 @@ private function checkBlankLineBeforeTags(File $phpcsFile, $commentStart) } } - /** - * @param int $commentStart - */ - private function checkTagsSpaces(File $phpcsFile, $commentStart) + private function checkTagsSpaces(File $phpcsFile, int $commentStart) : void { $tokens = $phpcsFile->getTokens(); @@ -817,10 +784,7 @@ private function checkTagsSpaces(File $phpcsFile, $commentStart) } } - /** - * @param int $tag - */ - private function checkSpacesAfterTag(File $phpcsFile, $tag) + private function checkSpacesAfterTag(File $phpcsFile, int $tag) : void { $tokens = $phpcsFile->getTokens(); diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 805c1aca..a6c3f3c2 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -49,7 +49,7 @@ class FunctionCommentSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_FUNCTION]; } @@ -84,11 +84,7 @@ public function process(File $phpcsFile, $stackPtr) } } - /** - * @param int $commentStart - * @param int $commentEnd - */ - private function processSee(File $phpcsFile, $commentStart, $commentEnd) + private function processSee(File $phpcsFile, int $commentStart, int $commentEnd) : void { $tokens = $phpcsFile->getTokens(); @@ -106,10 +102,7 @@ private function processSee(File $phpcsFile, $commentStart, $commentEnd) } } - /** - * @param int $commentStart - */ - private function processTagOrder(File $phpcsFile, $commentStart) + private function processTagOrder(File $phpcsFile, int $commentStart) : void { $tokens = $phpcsFile->getTokens(); diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionDataProviderTagSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionDataProviderTagSniff.php index c93f1f5c..892d33f7 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionDataProviderTagSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionDataProviderTagSniff.php @@ -24,7 +24,7 @@ class FunctionDataProviderTagSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_FUNCTION]; } diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionDisallowedTagSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionDisallowedTagSniff.php index 6a462170..15ed3edd 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionDisallowedTagSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionDisallowedTagSniff.php @@ -50,7 +50,7 @@ class FunctionDisallowedTagSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_FUNCTION]; } diff --git a/src/ZendCodingStandard/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseSniff.php index 7bda9422..2001db83 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseSniff.php @@ -16,7 +16,7 @@ class NoInlineCommentAfterCurlyCloseSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_CLOSE_CURLY_BRACKET]; } diff --git a/src/ZendCodingStandard/Sniffs/Commenting/TagCaseSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/TagCaseSniff.php index 87f7e313..663eb1aa 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/TagCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/TagCaseSniff.php @@ -85,7 +85,7 @@ class TagCaseSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_DOC_COMMENT_TAG]; } diff --git a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php index 588d2b8c..a3368c3f 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php @@ -29,7 +29,7 @@ class VariableCommentSniff extends AbstractVariableSniff /** * @param int $stackPtr */ - public function processMemberVar(File $phpcsFile, $stackPtr) + protected function processMemberVar(File $phpcsFile, $stackPtr) : void { $tokens = $phpcsFile->getTokens(); $ignore = [ @@ -125,7 +125,7 @@ public function processMemberVar(File $phpcsFile, $stackPtr) /** * @param int $stackPtr */ - protected function processVariable(File $phpcsFile, $stackPtr) + protected function processVariable(File $phpcsFile, $stackPtr) : void { // Sniff process only class member vars. } @@ -133,7 +133,7 @@ protected function processVariable(File $phpcsFile, $stackPtr) /** * @param int $stackPtr */ - protected function processVariableInString(File $phpcsFile, $stackPtr) + protected function processVariableInString(File $phpcsFile, $stackPtr) : void { // Sniff process only class member vars. } diff --git a/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php index e54f2025..a7c0f328 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/DoubleColonSniff.php @@ -15,7 +15,7 @@ class DoubleColonSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_DOUBLE_COLON]; } diff --git a/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php index c019f610..d8975152 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/NewKeywordSniff.php @@ -15,7 +15,7 @@ class NewKeywordSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_NEW]; } diff --git a/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php index 6efa885e..44fcba9f 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/NoSpaceAfterSplatSniff.php @@ -15,7 +15,7 @@ class NoSpaceAfterSplatSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_ELLIPSIS]; } diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php index c2d95eda..f32076c0 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReferenceSniff.php @@ -21,7 +21,7 @@ class ReferenceSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_BITWISE_AND]; } diff --git a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php index 4a665046..1dbc4be6 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php @@ -60,7 +60,7 @@ class ReturnTypeSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_RETURN_TYPE]; } @@ -143,10 +143,8 @@ public function process(File $phpcsFile, $stackPtr) /** * Check if token before colon match configured number of spaces. - * - * @param int $colon */ - private function checkSpacesBeforeColon(File $phpcsFile, $colon) + private function checkSpacesBeforeColon(File $phpcsFile, int $colon) : void { $tokens = $phpcsFile->getTokens(); @@ -189,10 +187,8 @@ private function checkSpacesBeforeColon(File $phpcsFile, $colon) /** * Check if token after colon match configured number of spaces. - * - * @param int $colon */ - private function checkSpacesAfterColon(File $phpcsFile, $colon) + private function checkSpacesAfterColon(File $phpcsFile, int $colon) : void { $tokens = $phpcsFile->getTokens(); @@ -228,10 +224,8 @@ private function checkSpacesAfterColon(File $phpcsFile, $colon) /** * Checks if token after nullable operator match configured number of spaces. - * - * @param int $nullable */ - private function checkSpacesAfterNullable(File $phpcsFile, $nullable) + private function checkSpacesAfterNullable(File $phpcsFile, int $nullable) : void { $tokens = $phpcsFile->getTokens(); diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php index eed65542..f7ebe2bd 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -98,7 +98,7 @@ class UnnecessaryParenthesesSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_OPEN_PARENTHESIS]; } @@ -248,12 +248,7 @@ public function process(File $phpcsFile, $stackPtr) } } - /** - * @param int $openPtr - * @param int $closePtr - * @param string $errorCode - */ - private function error(File $phpcsFile, $openPtr, $closePtr, $errorCode) + private function error(File $phpcsFile, int $openPtr, int $closePtr, string $errorCode) : void { $tokens = $phpcsFile->getTokens(); diff --git a/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php index 926ff7b4..977f6a4c 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php @@ -61,7 +61,7 @@ class ParamSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_FUNCTION]; } @@ -82,10 +82,7 @@ public function process(File $phpcsFile, $stackPtr) $this->processParamSpec($phpcsFile); } - /** - * @param int $commentStart - */ - private function processParamDoc(File $phpcsFile, $commentStart) + private function processParamDoc(File $phpcsFile, int $commentStart) : void { $params = []; $paramsMap = []; @@ -163,7 +160,7 @@ private function processParamDoc(File $phpcsFile, $commentStart) $phpcsFile->addError($error, $tag + 2, 'InvalidParamTypeDoc', $data); continue; } - $description = isset($split[2]) ? $split[2] : null; + $description = $split[2] ?? null; $type = $split[0]; $this->checkParam($phpcsFile, current($param), $tag, $name, $type, $description); @@ -191,9 +188,8 @@ private function processParamDoc(File $phpcsFile, $commentStart) /** * @param string[] $map - * @param int $wrong */ - private function fixParamOrder(File $phpcsFile, array $map, $wrong) + private function fixParamOrder(File $phpcsFile, array $map, int $wrong) : void { $tokens = $phpcsFile->getTokens(); @@ -246,11 +242,7 @@ private function fixParamOrder(File $phpcsFile, array $map, $wrong) $phpcsFile->fixer->endChangeset(); } - /** - * @param int $varPtr - * @param string $newTypeHint - */ - private function replaceParamTypeHint(File $phpcsFile, $varPtr, $newTypeHint) + private function replaceParamTypeHint(File $phpcsFile, int $varPtr, string $newTypeHint) : void { $last = $phpcsFile->findPrevious([T_ARRAY_HINT, T_CALLABLE, T_STRING], $varPtr - 1); $first = $phpcsFile->findPrevious([T_NULLABLE, T_STRING, T_NS_SEPARATOR], $last - 1, null, true); @@ -264,7 +256,7 @@ private function replaceParamTypeHint(File $phpcsFile, $varPtr, $newTypeHint) } /** - * @param string[] $param Real param function details. + * @param array $param Real param function details.z * @param null|int $tagPtr Position of the @param tag. * @param null|string $name Name of the param in the @param tag. * @param null|string $typeStr Type of the param in the @param tag. @@ -273,11 +265,11 @@ private function replaceParamTypeHint(File $phpcsFile, $varPtr, $newTypeHint) private function checkParam( File $phpcsFile, array $param, - $tagPtr = null, - $name = null, - $typeStr = null, - $description = null - ) { + int $tagPtr = null, + string $name = null, + string $typeStr = null, + string $description = null + ) : void { $typeHint = $param['type_hint']; if ($typeHint) { @@ -613,26 +605,18 @@ private function checkParam( } } - /** - * @param string $str - * @return bool - */ - private function isVariable($str) + private function isVariable(string $str) : bool { return strpos($str, '$') === 0 || strpos($str, '...$') === 0; } - /** - * @param string $str - * @return bool - */ - private function isType($str) + private function isType(string $str) : bool { return (bool) preg_match('/^((?:\\\\?[a-z0-9]+)+(?:\[\])*)(\|(?:\\\\?[a-z0-9]+)+(?:\[\])*)*$/i', $str); } - private function processParamSpec(File $phpcsFile) + private function processParamSpec(File $phpcsFile) : void { foreach ($this->params as $k => $param) { if (in_array($k, $this->processedParams, true)) { diff --git a/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php index 82ca93e1..95dc5274 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php @@ -89,7 +89,7 @@ class ReturnTypeSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_FUNCTION]; } @@ -119,10 +119,9 @@ public function process(File $phpcsFile, $stackPtr) } /** - * @param int $stackPtr * @return bool|int */ - private function getReturnType(File $phpcsFile, $stackPtr) + private function getReturnType(File $phpcsFile, int $stackPtr) { $tokens = $phpcsFile->getTokens(); @@ -135,10 +134,7 @@ private function getReturnType(File $phpcsFile, $stackPtr) return $phpcsFile->findNext(T_RETURN_TYPE, $stackPtr + 1, $to); } - /** - * @param int $commentStart - */ - private function processReturnDoc(File $phpcsFile, $commentStart) + private function processReturnDoc(File $phpcsFile, int $commentStart) : void { $tokens = $phpcsFile->getTokens(); @@ -403,10 +399,7 @@ private function processReturnDoc(File $phpcsFile, $commentStart) } } - /** - * @param int $stackPtr - */ - private function processReturnType(File $phpcsFile, $stackPtr) + private function processReturnType(File $phpcsFile, int $stackPtr) : void { // Get return type from method signature $returnType = $this->getReturnType($phpcsFile, $stackPtr); @@ -674,10 +667,7 @@ private function processReturnType(File $phpcsFile, $stackPtr) } } - /** - * @param int $stackPtr - */ - private function processReturnStatements(File $phpcsFile, $stackPtr) + private function processReturnStatements(File $phpcsFile, int $stackPtr) : void { $tokens = $phpcsFile->getTokens(); @@ -871,11 +861,7 @@ function ($a, $b) { } } - /** - * @param int $ptr - * @return string - */ - private function getReturnValue(File $phpcsFile, $ptr) + private function getReturnValue(File $phpcsFile, int $ptr) : string { $tokens = $phpcsFile->getTokens(); @@ -997,9 +983,8 @@ private function getReturnValue(File $phpcsFile, $ptr) /** * @param string[] $expectedType * @param string[] $expectedDoc - * @return bool */ - private function hasCorrectType(array $expectedType, array $expectedDoc) + private function hasCorrectType(array $expectedType, array $expectedDoc) : bool { if ($expectedType && $this->returnType @@ -1022,10 +1007,7 @@ private function hasCorrectType(array $expectedType, array $expectedDoc) return true; } - /** - * @param int $ptr - */ - private function returnCodeVoid(File $phpcsFile, $ptr) + private function returnCodeVoid(File $phpcsFile, int $ptr) : void { if (($this->returnDoc && $this->returnDocIsValid) || ($this->returnType && $this->returnTypeIsValid && strtolower($this->returnTypeValue) !== 'void') @@ -1036,10 +1018,7 @@ private function returnCodeVoid(File $phpcsFile, $ptr) } } - /** - * @param int $ptr - */ - private function returnCodeValue(File $phpcsFile, $ptr) + private function returnCodeValue(File $phpcsFile, int $ptr) : void { // Special method cannot return any values. if ($this->isSpecialMethod) { diff --git a/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php index dcd7b80f..03c88d24 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php @@ -46,7 +46,7 @@ class ThrowsSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_FUNCTION]; } @@ -66,10 +66,7 @@ public function process(File $phpcsFile, $stackPtr) $this->processThrowStatements($phpcsFile, $stackPtr); } - /** - * @param int $commentStart - */ - private function processThrowsDoc(File $phpcsFile, $commentStart) + private function processThrowsDoc(File $phpcsFile, int $commentStart) : void { $tokens = $phpcsFile->getTokens(); @@ -109,10 +106,7 @@ private function processThrowsDoc(File $phpcsFile, $commentStart) } } - /** - * @param int $stackPtr - */ - protected function processThrowStatements(File $phpcsFile, $stackPtr) + protected function processThrowStatements(File $phpcsFile, int $stackPtr) : void { $tokens = $phpcsFile->getTokens(); @@ -253,11 +247,9 @@ protected function processThrowStatements(File $phpcsFile, $stackPtr) } /** - * @param int $from - * @param int $to * @return string[] */ - private function getExceptions(File $phpcsFile, $from, $to) + private function getExceptions(File $phpcsFile, int $from, int $to) : array { $tokens = $phpcsFile->getTokens(); @@ -312,9 +304,8 @@ private function getExceptions(File $phpcsFile, $from, $to) * * @param string[] $conditions * @param int $scope Scope to check in conditions. - * @return bool */ - private function isLastScope(array $conditions, $scope) + private function isLastScope(array $conditions, int $scope) : bool { foreach (array_reverse($conditions, true) as $ptr => $code) { if ($code !== T_FUNCTION && $code !== T_CLOSURE && $code !== T_TRY) { diff --git a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php index 2aeb0e65..cf16c1c0 100644 --- a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php +++ b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php @@ -29,7 +29,7 @@ public function __construct() * @param int $stackPtr * @param int $currScope */ - protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) : void { $tokens = $phpcsFile->getTokens(); @@ -67,7 +67,7 @@ protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScop /** * @param int $stackPtr */ - protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) : void { } } diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php index e14f102b..4f243ea3 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -29,7 +29,7 @@ class AlphabeticallySortedUsesSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_NAMESPACE]; } @@ -133,10 +133,9 @@ public function process(File $phpcsFile, $stackPtr) } /** - * @param int $scopePtr * @return string[][] */ - private function getUseStatements(File $phpcsFile, $scopePtr) + private function getUseStatements(File $phpcsFile, int $scopePtr) : array { $tokens = $phpcsFile->getTokens(); @@ -193,9 +192,8 @@ private function getUseStatements(File $phpcsFile, $scopePtr) /** * @param string[] $a * @param string[] $b - * @return int */ - private function compareUseStatements(array $a, array $b) + private function compareUseStatements(array $a, array $b) : int { if ($a['type'] === $b['type']) { return strcasecmp( @@ -213,11 +211,7 @@ private function compareUseStatements(array $a, array $b) return 1; } - /** - * @param string $name - * @return string - */ - private function clearName($name) + private function clearName(string $name) : string { return str_replace('\\', ':', $name); } @@ -225,7 +219,7 @@ private function clearName($name) /** * @param string[][] $uses */ - private function fixAlphabeticalOrder(File $phpcsFile, array $uses) + private function fixAlphabeticalOrder(File $phpcsFile, array $uses) : void { $first = reset($uses); $last = end($uses); diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php index a082d9c4..c02bd433 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/ConstAndFunctionKeywordsSniff.php @@ -19,7 +19,7 @@ class ConstAndFunctionKeywordsSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_USE]; } diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index a0637c97..1b2134b4 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -55,7 +55,7 @@ class UnusedUseStatementSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_USE]; } diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php index f9d9149a..c82de103 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php @@ -21,7 +21,7 @@ class UseDoesNotStartWithBackslashSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_USE]; } diff --git a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php index 3ee8c970..6e0c9bf7 100644 --- a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php +++ b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -21,8 +21,6 @@ class ValidVariableNameSniff extends AbstractVariableSniff { - const CODE_CAMEL_CAPS = 'NotCamelCaps'; - /** @var string[] */ private $phpReservedVars = [ '_SERVER', @@ -39,7 +37,7 @@ class ValidVariableNameSniff extends AbstractVariableSniff /** * @param int $stackPtr */ - protected function processVariable(File $phpcsFile, $stackPtr) + protected function processVariable(File $phpcsFile, $stackPtr) : void { $tokens = $phpcsFile->getTokens(); $varName = ltrim($tokens[$stackPtr]['content'], '$'); @@ -57,14 +55,14 @@ protected function processVariable(File $phpcsFile, $stackPtr) if (! Common::isCamelCaps($varName, false, true, false)) { $error = 'Variable "%s" is not in valid camel caps format'; $data = [$varName]; - $phpcsFile->addError($error, $stackPtr, self::CODE_CAMEL_CAPS, $data); + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); } } /** * @param int $stackPtr */ - protected function processMemberVar(File $phpcsFile, $stackPtr) + protected function processMemberVar(File $phpcsFile, $stackPtr) : void { // handled by PSR2.Classes.PropertyDeclaration } @@ -72,7 +70,7 @@ protected function processMemberVar(File $phpcsFile, $stackPtr) /** * @param int $stackPtr */ - protected function processVariableInString(File $phpcsFile, $stackPtr) + protected function processVariableInString(File $phpcsFile, $stackPtr) : void { // handled by Squiz.Strings.DoubleQuoteUsage } diff --git a/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php b/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php index 617d7021..dca7a119 100644 --- a/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php +++ b/src/ZendCodingStandard/Sniffs/Operators/BooleanOperatorSniff.php @@ -15,7 +15,7 @@ class BooleanOperatorSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return Tokens::$booleanOperators; } diff --git a/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php b/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php index 3d922198..8ad5d3b7 100644 --- a/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php +++ b/src/ZendCodingStandard/Sniffs/Operators/TernaryOperatorSniff.php @@ -17,7 +17,7 @@ class TernaryOperatorSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [ T_INLINE_ELSE, @@ -92,11 +92,7 @@ public function process(File $phpcsFile, $stackPtr) } } - /** - * @param int $stackPtr - * @return null|int - */ - protected function findThen(File $phpcsFile, $stackPtr) + protected function findThen(File $phpcsFile, int $stackPtr) : ?int { $tokens = $phpcsFile->getTokens(); $count = 0; @@ -117,11 +113,7 @@ protected function findThen(File $phpcsFile, $stackPtr) return null; } - /** - * @param int $stackPtr - * @return null|int - */ - protected function findElse(File $phpcsFile, $stackPtr) + protected function findElse(File $phpcsFile, int $stackPtr) : ?int { $tokens = $phpcsFile->getTokens(); $count = 0; diff --git a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index 2dfcf971..ce1edb1f 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -74,7 +74,7 @@ public function __construct() /** * @return int[] */ - public function register() + public function register() : array { return [ T_NEW, @@ -126,10 +126,8 @@ public function process(File $phpcsFile, $stackPtr) /** * Checks statement before double colon - "ClassName::". - * - * @param int $stackPtr */ - private function checkDoubleColon(File $phpcsFile, $stackPtr) + private function checkDoubleColon(File $phpcsFile, int $stackPtr) : void { $tokens = $phpcsFile->getTokens(); @@ -156,10 +154,8 @@ private function checkDoubleColon(File $phpcsFile, $stackPtr) /** * Checks "new ClassName" statements. - * - * @param int $stackPtr */ - private function checkNew(File $phpcsFile, $stackPtr) + private function checkNew(File $phpcsFile, int $stackPtr) : void { $tokens = $phpcsFile->getTokens(); @@ -185,10 +181,8 @@ private function checkNew(File $phpcsFile, $stackPtr) /** * Checks "use" statements - global and traits. - * - * @param int $stackPtr */ - private function checkUse(File $phpcsFile, $stackPtr) + private function checkUse(File $phpcsFile, int $stackPtr) : void { $tokens = $phpcsFile->getTokens(); @@ -219,10 +213,8 @@ private function checkUse(File $phpcsFile, $stackPtr) /** * Checks params type hints - * - * @param int $stackPtr */ - private function checkFunctionParams(File $phpcsFile, $stackPtr) + private function checkFunctionParams(File $phpcsFile, int $stackPtr) : void { $params = $phpcsFile->getMethodParameters($stackPtr); @@ -240,11 +232,9 @@ private function checkFunctionParams(File $phpcsFile, $stackPtr) } /** - * Checks return type (PHP 7) - * - * @param int $stackPtr + * Checks return type */ - private function checkReturnType(File $phpcsFile, $stackPtr) + private function checkReturnType(File $phpcsFile, int $stackPtr) : void { $before = $phpcsFile->findPrevious([T_COLON, T_NULLABLE], $stackPtr - 1); $first = $phpcsFile->findNext(Tokens::$emptyTokens, $before + 1, null, true); @@ -254,10 +244,8 @@ private function checkReturnType(File $phpcsFile, $stackPtr) /** * Checks PHPDocs tags - * - * @param int $stackPtr */ - private function checkTag(File $phpcsFile, $stackPtr) + private function checkTag(File $phpcsFile, int $stackPtr) : void { $tokens = $phpcsFile->getTokens(); @@ -269,7 +257,7 @@ private function checkTag(File $phpcsFile, $stackPtr) } $string = $tokens[$stackPtr + 2]['content']; - list($types) = explode(' ', $string); + [$types] = explode(' ', $string); $typesArr = explode('|', $types); $newTypesArr = []; @@ -300,12 +288,8 @@ private function checkTag(File $phpcsFile, $stackPtr) /** * Returns expected class name for given $class. - * - * @param string $class - * @param int $stackPtr - * @return string */ - private function getExpectedName(File $phpcsFile, $class, $stackPtr) + private function getExpectedName(File $phpcsFile, string $class, int $stackPtr) : string { if ($class[0] === '\\') { $result = $this->hasDifferentCase(ltrim($class, '\\')); @@ -339,10 +323,8 @@ private function getExpectedName(File $phpcsFile, $class, $stackPtr) /** * Checks "extends" and "implements" classes/interfaces. - * - * @param int $stackPtr */ - private function checkExtendsAndImplements(File $phpcsFile, $stackPtr) + private function checkExtendsAndImplements(File $phpcsFile, int $stackPtr) : void { $tokens = $phpcsFile->getTokens(); @@ -369,12 +351,8 @@ private function checkExtendsAndImplements(File $phpcsFile, $stackPtr) /** * Checks if class is used correctly. - * - * @param int $start - * @param int $end - * @param bool $isGlobalUse */ - private function checkClass(File $phpcsFile, $start, $end, $isGlobalUse = false) + private function checkClass(File $phpcsFile, int $start, int $end, bool $isGlobalUse = false) : void { $class = trim($phpcsFile->getTokensAsString($start, $end - $start)); if ($class[0] === '\\') { @@ -415,13 +393,8 @@ private function checkClass(File $phpcsFile, $start, $end, $isGlobalUse = false) /** * Reports new fixable error. - * - * @param int $start - * @param int $end - * @param string $expected - * @param string $actual */ - private function error(File $phpcsFile, $start, $end, $expected, $actual) + private function error(File $phpcsFile, int $start, int $end, string $expected, string $actual) : void { $error = 'Invalid class name case: expected %s; found %s'; $data = [ @@ -443,22 +416,19 @@ private function error(File $phpcsFile, $start, $end, $expected, $actual) /** * Checks if class is defined and has different case - then returns class name * with correct case. Otherwise returns false. - * - * @param string $class - * @return false|string */ - private function hasDifferentCase($class) + private function hasDifferentCase(string $class) : ?string { - $index = array_search(strtolower($class), array_map('strtolower', $this->declaredClasses)); + $index = array_search(strtolower($class), array_map('strtolower', $this->declaredClasses), true); if ($index === false) { // Not defined? - return false; + return null; } if ($this->declaredClasses[$index] === $class) { // Exactly the same. - return false; + return null; } return $this->declaredClasses[$index]; diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php index f316cf79..f22fe2b9 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php @@ -72,7 +72,7 @@ public function __construct() /** * @return int[] */ - public function register() + public function register() : array { return [T_STRING]; } @@ -169,11 +169,7 @@ public function process(File $phpcsFile, $stackPtr) } } - /** - * @param int $stackPtr - * @param string $constantName - */ - private function importConstant(File $phpcsFile, $stackPtr, $constantName) + private function importConstant(File $phpcsFile, int $stackPtr, string $constantName) : void { if ($this->lastUse) { $ptr = $phpcsFile->findEndOfStatement($this->lastUse); diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php index 6e7e521d..ef5f84fa 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php @@ -63,7 +63,7 @@ public function __construct() /** * @return int[] */ - public function register() + public function register() : array { return [T_STRING]; } @@ -157,11 +157,7 @@ public function process(File $phpcsFile, $stackPtr) } } - /** - * @param int $stackPtr - * @param string $functionName - */ - private function importFunction(File $phpcsFile, $stackPtr, $functionName) + private function importFunction(File $phpcsFile, int $stackPtr, string $functionName) : void { if ($this->lastUse) { $ptr = $phpcsFile->findEndOfStatement($this->lastUse); diff --git a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php index d63848ea..c5fdaf0a 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php @@ -24,7 +24,7 @@ class InstantiatingParenthesisSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_NEW]; } diff --git a/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php b/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php index 8263a957..b1daa068 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/RedundantSemicolonSniff.php @@ -21,7 +21,7 @@ class RedundantSemicolonSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_CLOSE_CURLY_BRACKET]; } diff --git a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php index 461fe85d..69bf7b5d 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -27,7 +27,7 @@ class TypeCastingSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return Tokens::$castTokens + [T_BOOLEAN_NOT => T_BOOLEAN_NOT]; @@ -67,7 +67,7 @@ public function process(File $phpcsFile, $stackPtr) $expected = preg_replace('/\s/', '', strtolower($content)); if ($content !== $expected || isset($this->castMap[$expected])) { $error = 'Invalid casting used. Expected %s, found %s'; - $expected = isset($this->castMap[$expected]) ? $this->castMap[$expected] : $expected; + $expected = $this->castMap[$expected] ?? $expected; $data = [ $expected, $content, diff --git a/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php b/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php index b4c5342c..8dd25e30 100644 --- a/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php +++ b/src/ZendCodingStandard/Sniffs/Strings/NoConcatenationAtTheEndSniff.php @@ -15,7 +15,7 @@ class NoConcatenationAtTheEndSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_STRING_CONCAT]; } diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php index a8fb3254..2ae6779c 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/BlankLineSniff.php @@ -16,7 +16,7 @@ class BlankLineSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [ T_COMMENT, diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php index 91ccb94d..e437a475 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -35,7 +35,7 @@ class CommaSpacingSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [T_COMMA]; } diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php index b05cbb4d..366df920 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/NoBlankLineAtStartSniff.php @@ -19,7 +19,7 @@ class NoBlankLineAtStartSniff implements Sniff /** * @return int[] */ - public function register() + public function register() : array { return [ T_CLASS, diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index 214e26eb..e3bfbb41 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -138,7 +138,7 @@ public function __construct() /** * @return int[] */ - public function register() + public function register() : array { return [T_OPEN_TAG]; } @@ -718,11 +718,8 @@ public function process(File $phpcsFile, $stackPtr) /** * @todo: need name refactor and method description - * - * @param int $ptr - * @return null|int */ - private function fp(File $phpcsFile, $ptr) + private function fp(File $phpcsFile, int $ptr) : ?int { if ($this->alignObjectOperators) { $tokens = $phpcsFile->getTokens(); @@ -749,11 +746,8 @@ private function fp(File $phpcsFile, $ptr) /** * @todo: need name refactor and method description - * - * @param int $ptr - * @return null|int */ - private function np(File $phpcsFile, $ptr) + private function np(File $phpcsFile, int $ptr) : ?int { $tokens = $phpcsFile->getTokens(); @@ -777,11 +771,8 @@ private function np(File $phpcsFile, $ptr) /** * Checks if there is another object operator * before $ptr token. - * - * @param int $ptr - * @return null|int */ - private function hasPrevObjectOperator(File $phpcsFile, $ptr) + private function hasPrevObjectOperator(File $phpcsFile, int $ptr) : ?int { $tokens = $phpcsFile->getTokens(); @@ -803,12 +794,8 @@ private function hasPrevObjectOperator(File $phpcsFile, $ptr) /** * Checks if between $fromPtr and $toPtr is any new line * excluding scopes (arrays, closures, multiline function calls). - * - * @param int $fromPtr - * @param int $toPtr - * @return bool */ - private function hasContainNewLine(File $phpcsFile, $fromPtr, $toPtr) + private function hasContainNewLine(File $phpcsFile, int $fromPtr, int $toPtr) : bool { $tokens = $phpcsFile->getTokens(); @@ -841,10 +828,9 @@ private function hasContainNewLine(File $phpcsFile, $fromPtr, $toPtr) * and returns the control structure pointer; * otherwise returns boolean `false`. * - * @param int $ptr * @return false|int */ - private function getControlStructurePtr(File $phpcsFile, $ptr) + private function getControlStructurePtr(File $phpcsFile, int $ptr) { $tokens = $phpcsFile->getTokens(); From 5cac3628e149d49c477de594f30f9fef4360f0d1 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 15 Feb 2018 11:10:12 +0000 Subject: [PATCH 169/225] Fixed doc-comment indent fixer with nested tags --- .../Sniffs/Commenting/DocCommentSniff.php | 2 +- test/Sniffs/Commenting/DocCommentUnitTest.inc | 11 +++++++++++ test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed | 11 +++++++++++ test/Sniffs/Commenting/DocCommentUnitTest.php | 5 +++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index f259db00..38a274db 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -408,7 +408,7 @@ private function checkSpacesAfterStar(File $phpcsFile, int $commentStart, int $c $fix = $phpcsFile->addFixableError($error, $next + 1, 'TooManySpacesAfterStar', $data); if ($fix) { - $phpcsFile->fixer->replaceToken($next + 1, ' '); + $phpcsFile->fixer->replaceToken($next + 1, $expected); } } elseif ($tokens[$next + 2]['code'] !== T_DOC_COMMENT_TAG && $tokens[$next + 2]['code'] !== T_DOC_COMMENT_CLOSE_TAG diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc b/test/Sniffs/Commenting/DocCommentUnitTest.inc index 0fd7dd36..8949b845 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc @@ -208,4 +208,15 @@ class Foo public function test10(array $arr) { } + + /** + * @param array $a { + * @var array { + * @var string $val Descr + * iption. + * @var bool $req + * } + * } + */ + private function twoLevelNesting(array $a) {} } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed index 879f5b9a..e4c1227b 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed @@ -210,4 +210,15 @@ $c = 'xyz'; public function test10(array $arr) { } + + /** + * @param array $a { + * @var array { + * @var string $val Descr + * iption. + * @var bool $req + * } + * } + */ + private function twoLevelNesting(array $a) {} } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.php b/test/Sniffs/Commenting/DocCommentUnitTest.php index 4cb7b012..a0939526 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.php +++ b/test/Sniffs/Commenting/DocCommentUnitTest.php @@ -159,6 +159,11 @@ public function getErrorList($testFile = '') 185 => 1, 192 => 1, 203 => 1, + 214 => 1, + 215 => 1, + 216 => 1, + 217 => 1, + 218 => 1, ]; } From 96fe4a6b5a74f44ed31c4c924d891dfaefb0b923 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 15 Feb 2018 11:12:07 +0000 Subject: [PATCH 170/225] Fixed calculating empty lines between tag with nested tags --- .../Sniffs/Commenting/FunctionCommentSniff.php | 8 +++++++- test/Sniffs/Commenting/FunctionCommentUnitTest.inc | 9 +++++++++ test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed | 8 ++++++++ test/Sniffs/Commenting/FunctionCommentUnitTest.php | 1 + 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index a6c3f3c2..a4085596 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -108,6 +108,7 @@ private function processTagOrder(File $phpcsFile, int $commentStart) : void $tags = $tokens[$commentStart]['comment_tags']; + $nestedTags = []; $data = []; while ($tag = current($tags)) { $key = key($tags); @@ -155,6 +156,8 @@ private function processTagOrder(File $phpcsFile, int $commentStart) : void $last = $i; while (isset($tags[$key + 1]) && $tags[$key + 1] < $i) { + $nestedTags[] = $tags[$key + 1]; + next($tags); ++$key; } @@ -231,7 +234,10 @@ private function processTagOrder(File $phpcsFile, int $commentStart) : void continue; } - $prevTag = $tags[$key - 1]; + $i = $key; + do { + $prevTag = $tags[--$i]; + } while (in_array($prevTag, $nestedTags, true)); if (in_array($tokens[$tag]['content'], $this->blankLineBefore, true) && $tokens[$prevTag]['content'] !== $tokens[$tag]['content'] ) { diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc index 7ca8d629..04a8ce9f 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc @@ -64,4 +64,13 @@ class Foo * } */ private function longParams($a) {} + + /** + * @param array $a { + * @var string $hola + * } + * + * @param int $b + */ + private function noEmptyLineBetweenLongDefParamAndAnoterParam(array $a, $b) {} } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed index ad647f2e..08d040b0 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed @@ -60,4 +60,12 @@ class Foo * } */ private function longParams($a) {} + + /** + * @param array $a { + * @var string $hola + * } + * @param int $b + */ + private function noEmptyLineBetweenLongDefParamAndAnoterParam(array $a, $b) {} } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.php b/test/Sniffs/Commenting/FunctionCommentUnitTest.php index c439c0f7..2ff6afef 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.php +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.php @@ -25,6 +25,7 @@ public function getErrorList($testFile = '') 42 => 1, 49 => 1, 57 => 1, + 72 => 1, ]; } From 50e2b1966bd21380279c1a1665c6d5a6a6ca3e93 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 15 Feb 2018 11:13:08 +0000 Subject: [PATCH 171/225] Added restriction for nested tags - currently allowed only `@var` --- .../Commenting/FunctionCommentSniff.php | 20 ++++++++++++++++ .../Commenting/FunctionCommentUnitTest.inc | 24 +++++++++++++++++++ .../FunctionCommentUnitTest.inc.fixed | 24 +++++++++++++++++++ .../Commenting/FunctionCommentUnitTest.php | 2 ++ 4 files changed, 70 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index a4085596..cc564bc0 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -8,6 +8,7 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use function array_filter; use function array_search; use function current; use function in_array; @@ -46,6 +47,13 @@ class FunctionCommentSniff implements Sniff '@param', ]; + /** + * @var string[] + */ + public $nestedTags = [ + '@var', + ]; + /** * @return int[] */ @@ -156,6 +164,18 @@ private function processTagOrder(File $phpcsFile, int $commentStart) : void $last = $i; while (isset($tags[$key + 1]) && $tags[$key + 1] < $i) { + $tagName = strtolower($tokens[$tags[$key + 1]]['content']); + if (! array_filter($this->nestedTags, function ($v) use ($tagName) { + return strtolower($v) === $tagName; + })) { + $error = 'Tag %s cannot be nested.'; + $data = [ + $tokens[$tags[$key + 1]]['content'], + ]; + $phpcsFile->addError($error, $tags[$key + 1], 'NestedTag', $data); + return; + } + $nestedTags[] = $tags[$key + 1]; next($tags); diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc index 04a8ce9f..d4a688d0 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc @@ -73,4 +73,28 @@ class Foo * @param int $b */ private function noEmptyLineBetweenLongDefParamAndAnoterParam(array $a, $b) {} + + /** + * @param array $a { + * @param string $hey + * } + */ + private function notAllowedNestedParam(array $a) {} + + /** + * @param array $a { + * @var string $hi + * @var bool $required + */ + private function missingClosingCurlyBRacket(array $a) {} + + /** + * @param array $a { + * @var array { + * @var string $val + * @var bool $req + * } + * } + */ + private function twoLevelNesting(array $a) {} } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed index 08d040b0..d6124f2c 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed @@ -68,4 +68,28 @@ class Foo * @param int $b */ private function noEmptyLineBetweenLongDefParamAndAnoterParam(array $a, $b) {} + + /** + * @param array $a { + * @param string $hey + * } + */ + private function notAllowedNestedParam(array $a) {} + + /** + * @param array $a { + * @var string $hi + * @var bool $required + */ + private function missingClosingCurlyBRacket(array $a) {} + + /** + * @param array $a { + * @var array { + * @var string $val + * @var bool $req + * } + * } + */ + private function twoLevelNesting(array $a) {} } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.php b/test/Sniffs/Commenting/FunctionCommentUnitTest.php index 2ff6afef..d0415034 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.php +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.php @@ -26,6 +26,8 @@ public function getErrorList($testFile = '') 49 => 1, 57 => 1, 72 => 1, + 79 => 1, + 85 => 1, ]; } From 5a87887dc49527c68e44a9160e24eb94a879905f Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 15 Feb 2018 11:14:50 +0000 Subject: [PATCH 172/225] Enable ImportInternalConstant and ImportInternalFunction sniffs --- ruleset.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/ruleset.xml b/ruleset.xml index b66b5d03..35c6319a 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -1,12 +1,4 @@ - - - - - - - - From 404b6c5ef73a3ad6069159f3cac60e06ec5a6f01 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 15 Feb 2018 13:31:32 +0000 Subject: [PATCH 173/225] Added new sniffs - Generic.Formatting.MultipleStatementAlignment - single space before assignment operator - Generic.PHP.DiscourageGoto --- src/ZendCodingStandard/Helper/Namespaces.php | 6 +++--- src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php | 2 +- src/ZendCodingStandard/ruleset.xml | 9 ++++++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/ZendCodingStandard/Helper/Namespaces.php b/src/ZendCodingStandard/Helper/Namespaces.php index ef9e6029..1fb6f985 100644 --- a/src/ZendCodingStandard/Helper/Namespaces.php +++ b/src/ZendCodingStandard/Helper/Namespaces.php @@ -46,7 +46,7 @@ private function getNamespace(File $phpcsFile, int $stackPtr) : string private function getGlobalUses(File $phpcsFile, int $stackPtr = 0) : array { $first = 0; - $last = $phpcsFile->numTokens; + $last = $phpcsFile->numTokens; $tokens = $phpcsFile->getTokens(); @@ -98,7 +98,7 @@ private function getGlobalUses(File $phpcsFile, int $stackPtr = 0) : array private function getImportedConstants(File $phpcsFile, int $stackPtr, ?int &$lastUse) : array { $first = 0; - $last = $phpcsFile->numTokens; + $last = $phpcsFile->numTokens; $tokens = $phpcsFile->getTokens(); @@ -150,7 +150,7 @@ private function getImportedConstants(File $phpcsFile, int $stackPtr, ?int &$las private function getImportedFunctions(File $phpcsFile, int $stackPtr, ?int &$lastUse) : array { $first = 0; - $last = $phpcsFile->numTokens; + $last = $phpcsFile->numTokens; $tokens = $phpcsFile->getTokens(); diff --git a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php index cf16c1c0..787faa06 100644 --- a/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php +++ b/src/ZendCodingStandard/Sniffs/Methods/LineAfterSniff.php @@ -40,7 +40,7 @@ protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScop $closer = $phpcsFile->findNext(T_SEMICOLON, $tokens[$stackPtr]['parenthesis_closer'] + 1); } - $contentAfter = $phpcsFile->findNext(T_WHITESPACE, $closer + 1, null, true); + $contentAfter = $phpcsFile->findNext(T_WHITESPACE, $closer + 1, null, true); if ($contentAfter !== false && $tokens[$contentAfter]['line'] - $tokens[$closer]['line'] !== 2 && $tokens[$contentAfter]['code'] !== T_CLOSE_CURLY_BRACKET diff --git a/src/ZendCodingStandard/ruleset.xml b/src/ZendCodingStandard/ruleset.xml index c0c229db..0d325a1e 100755 --- a/src/ZendCodingStandard/ruleset.xml +++ b/src/ZendCodingStandard/ruleset.xml @@ -26,9 +26,16 @@ + + + + + + + + - From 79c3970fcc6f7b2ef8110fa1d057b03083669ade Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 15 Feb 2018 13:52:01 +0000 Subject: [PATCH 174/225] Arrays.FormatSniffs now extends AbstractArraySniff --- .../Sniffs/Arrays/FormatSniff.php | 142 ++++++++---------- 1 file changed, 64 insertions(+), 78 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index fa5aad28..bbb06f08 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -5,7 +5,7 @@ namespace ZendCodingStandard\Sniffs\Arrays; use PHP_CodeSniffer\Files\File; -use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Sniffs\AbstractArraySniff; use function str_repeat; use function strlen; @@ -14,10 +14,9 @@ use const T_CLOSE_SHORT_ARRAY; use const T_COMMENT; use const T_DOUBLE_ARROW; -use const T_OPEN_SHORT_ARRAY; use const T_WHITESPACE; -class FormatSniff implements Sniff +class FormatSniff extends AbstractArraySniff { /** * The number of spaces code should be indented. @@ -27,80 +26,98 @@ class FormatSniff implements Sniff public $indent = 4; /** - * @return int[] - */ - public function register() : array - { - return [T_OPEN_SHORT_ARRAY]; - } - - /** - * @param int $stackPtr + * Processes a single-line array definition. + * + * @param File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. */ - public function process(File $phpcsFile, $stackPtr) + protected function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) : void { $tokens = $phpcsFile->getTokens(); - $arrayToken = $tokens[$stackPtr]; - $bracketOpener = $arrayToken['bracket_opener']; - $bracketCloser = $arrayToken['bracket_closer']; + // Single-line array - spaces before first element + if ($tokens[$arrayStart + 1]['code'] === T_WHITESPACE) { + $error = 'Expected 0 spaces after array bracket opener; %d found'; + $data = [strlen($tokens[$arrayStart + 1]['content'])]; + $fix = $phpcsFile->addFixableError($error, $arrayStart + 1, 'SingleLineSpaceBefore', $data); - if ($tokens[$bracketOpener]['line'] !== $tokens[$bracketCloser]['line']) { - $this->multiLineArray($phpcsFile, $stackPtr); - return; + if ($fix) { + $phpcsFile->fixer->replaceToken($arrayStart + 1, ''); + } } - $this->singleLineArray($phpcsFile, $stackPtr); + // Single-line array - spaces before last element + if ($tokens[$arrayEnd - 1]['code'] === T_WHITESPACE) { + $error = 'Expected 0 spaces before array bracket closer; %d found'; + $data = [strlen($tokens[$arrayEnd - 1]['content'])]; + $fix = $phpcsFile->addFixableError($error, $arrayEnd - 1, 'SingleLineSpaceAfter', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($arrayEnd - 1, ''); + } + } } - private function multiLineArray(File $phpcsFile, int $stackPtr) : void + /** + * Processes a multi-line array definition. + * + * @param File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + */ + protected function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) : void { $tokens = $phpcsFile->getTokens(); - $arrayToken = $tokens[$stackPtr]; - $bracketOpener = $arrayToken['bracket_opener']; - $bracketCloser = $arrayToken['bracket_closer']; - - $firstContent = $phpcsFile->findNext(T_WHITESPACE, $bracketOpener + 1, null, true); + $firstContent = $phpcsFile->findNext(T_WHITESPACE, $arrayStart + 1, null, true); if ($tokens[$firstContent]['code'] === T_CLOSE_SHORT_ARRAY) { - $error = 'Empty array must be in one line.'; + $error = 'Empty array must be in one line'; $fix = $phpcsFile->addFixableError($error, $stackPtr, 'EmptyArrayInOneLine'); if ($fix) { - $phpcsFile->fixer->replaceToken($bracketOpener + 1, ''); + $phpcsFile->fixer->replaceToken($arrayStart + 1, ''); } return; } - $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $bracketCloser - 1, null, true); - if ($tokens[$bracketCloser]['line'] > $tokens[$lastContent]['line'] + 1) { - $error = 'Blank line found at the end of array'; - $fix = $phpcsFile->addFixableError($error, $bracketCloser - 1, 'BlankLineAtTheEnd'); + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $arrayEnd - 1, null, true); + if ($tokens[$arrayEnd]['line'] > $tokens[$lastContent]['line'] + 1) { + $error = 'Blank line found at the end of the array'; + $fix = $phpcsFile->addFixableError($error, $arrayEnd - 1, 'BlankLineAtTheEnd'); if ($fix) { $phpcsFile->fixer->beginChangeset(); $i = $lastContent + 1; - while ($tokens[$i]['line'] !== $tokens[$bracketCloser]['line']) { + while ($tokens[$i]['line'] !== $tokens[$arrayEnd]['line']) { $phpcsFile->fixer->replaceToken($i, ''); ++$i; } - $phpcsFile->fixer->addNewlineBefore($bracketCloser); + $phpcsFile->fixer->addNewlineBefore($arrayEnd); $phpcsFile->fixer->endChangeset(); } } - $first = $phpcsFile->findFirstOnLine([], $bracketOpener, true); + $first = $phpcsFile->findFirstOnLine([], $arrayStart, true); $indent = $tokens[$first]['code'] === T_WHITESPACE ? strlen($tokens[$first]['content']) : 0; - $previousLine = $tokens[$bracketOpener]['line']; - $next = $bracketOpener; - while ($next = $phpcsFile->findNext(T_WHITESPACE, $next + 1, $bracketCloser, true)) { + $previousLine = $tokens[$arrayStart]['line']; + $next = $arrayStart; + while ($next = $phpcsFile->findNext(T_WHITESPACE, $next + 1, $arrayEnd, true)) { if ($previousLine === $tokens[$next]['line']) { if ($tokens[$next]['code'] !== T_COMMENT) { - $error = 'There must be one array element per line.'; + $error = 'There must be one array element per line'; $fix = $phpcsFile->addFixableError($error, $next, 'OneElementPerLine'); if ($fix) { @@ -115,11 +132,11 @@ private function multiLineArray(File $phpcsFile, int $stackPtr) : void } else { if ($previousLine < $tokens[$next]['line'] - 1 && (! empty($tokens[$stackPtr]['conditions']) - || $previousLine === $tokens[$bracketOpener]['line']) + || $previousLine === $tokens[$arrayStart]['line']) ) { $firstOnLine = $phpcsFile->findFirstOnLine([], $next, true); - $error = 'Blank line is not allowed here.'; + $error = 'Blank line is not allowed here'; $fix = $phpcsFile->addFixableError($error, $firstOnLine - 1, 'BlankLine'); if ($fix) { @@ -144,51 +161,20 @@ private function multiLineArray(File $phpcsFile, int $stackPtr) : void $next = $end; } - if ($first = $phpcsFile->findFirstOnLine([], $bracketCloser, true)) { - if ($first < $bracketCloser - 1) { - $error = 'Array closing bracket should be in new line.'; - $fix = $phpcsFile->addFixableError($error, $bracketCloser, 'ClosingBracketInNewLine'); + if ($first = $phpcsFile->findFirstOnLine([], $arrayEnd, true)) { + if ($first < $arrayEnd - 1) { + $error = 'Array closing bracket should be in new line'; + $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'ClosingBracketInNewLine'); if ($fix) { $phpcsFile->fixer->beginChangeset(); if ($indent > 0) { - $phpcsFile->fixer->addContentBefore($bracketCloser, str_repeat(' ', $indent)); + $phpcsFile->fixer->addContentBefore($arrayEnd, str_repeat(' ', $indent)); } - $phpcsFile->fixer->addNewlineBefore($bracketCloser); + $phpcsFile->fixer->addNewlineBefore($arrayEnd); $phpcsFile->fixer->endChangeset(); } } } } - - private function singleLineArray(File $phpcsFile, int $stackPtr) : void - { - $tokens = $phpcsFile->getTokens(); - $arrayToken = $tokens[$stackPtr]; - - $bracketOpener = $arrayToken['bracket_opener']; - $bracketCloser = $arrayToken['bracket_closer']; - - // Single-line array - spaces before first element - if ($tokens[$bracketOpener + 1]['code'] === T_WHITESPACE) { - $error = 'Expected 0 spaces after array bracket opener; %d found'; - $data = [strlen($tokens[$bracketOpener + 1]['content'])]; - $fix = $phpcsFile->addFixableError($error, $bracketOpener + 1, 'SingleLineSpaceBefore', $data); - - if ($fix) { - $phpcsFile->fixer->replaceToken($bracketOpener + 1, ''); - } - } - - // Single-line array - spaces before last element - if ($tokens[$bracketCloser - 1]['code'] === T_WHITESPACE) { - $error = 'Expected 0 spaces before array bracket closer; %d found'; - $data = [strlen($tokens[$bracketCloser - 1]['content'])]; - $fix = $phpcsFile->addFixableError($error, $bracketCloser - 1, 'SingleLineSpaceAfter', $data); - - if ($fix) { - $phpcsFile->fixer->replaceToken($bracketCloser - 1, ''); - } - } - } } From 8ca89740b7a4c0ce1b21dbb31aee68224b748f36 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 15 Feb 2018 14:06:44 +0000 Subject: [PATCH 175/225] Removed duplicated sniff - Generic.Files.OneTraitPerFile It is covered by PSR1.Classes.ClassDeclarationSniff --- src/ZendCodingStandard/ruleset.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ZendCodingStandard/ruleset.xml b/src/ZendCodingStandard/ruleset.xml index 0d325a1e..756858aa 100755 --- a/src/ZendCodingStandard/ruleset.xml +++ b/src/ZendCodingStandard/ruleset.xml @@ -26,7 +26,6 @@ - From 31df9a236c5013f6043f08d983e6f93b7b103652 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 21 Feb 2018 14:47:03 +0000 Subject: [PATCH 176/225] Updated to PHP_CodeSniffer 3.2.3 --- composer.json | 2 +- composer.lock | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/composer.json b/composer.json index 0574ec4d..7209b89d 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ ], "require": { "php": "^7.1", - "squizlabs/php_codesniffer": "3.2.2" + "squizlabs/php_codesniffer": "3.2.3" }, "require-dev": { "phpunit/phpunit": "^7.0.1" diff --git a/composer.lock b/composer.lock index 5382a836..a3b622bf 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "2379eab2896b6b8a22ce5e31fb6ae184", + "content-hash": "2528f561888e57981d5f87311dcf666c", "packages": [ { "name": "squizlabs/php_codesniffer", - "version": "3.2.2", + "version": "3.2.3", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "d7c00c3000ac0ce79c96fcbfef86b49a71158cd1" + "reference": "4842476c434e375f9d3182ff7b89059583aa8b27" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d7c00c3000ac0ce79c96fcbfef86b49a71158cd1", - "reference": "d7c00c3000ac0ce79c96fcbfef86b49a71158cd1", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/4842476c434e375f9d3182ff7b89059583aa8b27", + "reference": "4842476c434e375f9d3182ff7b89059583aa8b27", "shasum": "" }, "require": { @@ -27,7 +27,7 @@ "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, "bin": [ "bin/phpcs", @@ -55,7 +55,7 @@ "phpcs", "standards" ], - "time": "2017-12-19T21:44:46+00:00" + "time": "2018-02-20T21:35:23+00:00" } ], "packages-dev": [ @@ -414,16 +414,16 @@ }, { "name": "phpspec/prophecy", - "version": "1.7.4", + "version": "1.7.5", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "9f901e29c93dae4aa77c0bb161df4276f9c9a1be" + "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/9f901e29c93dae4aa77c0bb161df4276f9c9a1be", - "reference": "9f901e29c93dae4aa77c0bb161df4276f9c9a1be", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", + "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", "shasum": "" }, "require": { @@ -473,7 +473,7 @@ "spy", "stub" ], - "time": "2018-02-11T18:49:29+00:00" + "time": "2018-02-19T10:16:54+00:00" }, { "name": "phpunit/php-code-coverage", @@ -806,16 +806,16 @@ }, { "name": "phpunit/phpunit-mock-objects", - "version": "6.0.0", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "e495e5d3660321b62c294d8c0e954d02d6ce2573" + "reference": "e3249dedc2d99259ccae6affbc2684eac37c2e53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/e495e5d3660321b62c294d8c0e954d02d6ce2573", - "reference": "e495e5d3660321b62c294d8c0e954d02d6ce2573", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/e3249dedc2d99259ccae6affbc2684eac37c2e53", + "reference": "e3249dedc2d99259ccae6affbc2684eac37c2e53", "shasum": "" }, "require": { @@ -858,7 +858,7 @@ "mock", "xunit" ], - "time": "2018-02-01T13:11:13+00:00" + "time": "2018-02-15T05:27:38+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", From a93f494474bb2372edfeb9b4c76c0bacd4ee3e0c Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 21 Feb 2018 14:47:42 +0000 Subject: [PATCH 177/225] Removed unused while statement in UnusedUseStatementSniff --- .../Sniffs/Namespaces/UnusedUseStatementSniff.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index 1b2134b4..349a4135 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -24,7 +24,6 @@ use function preg_quote; use function rtrim; use function strcasecmp; -use function strpos; use function strtolower; use function trim; @@ -206,13 +205,8 @@ public function process(File $phpcsFile, $stackPtr) } // Also remove whitespace after the semicolon (new lines). - while (isset($tokens[$i]) && $tokens[$i]['code'] === T_WHITESPACE) { + if (isset($tokens[$i]) && $tokens[$i]['code'] === T_WHITESPACE) { $phpcsFile->fixer->replaceToken($i, ''); - if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false) { - break; - } - - ++$i; } $phpcsFile->fixer->endChangeset(); From bb67bda71e2d3ff8ec4dabeb6699babb867e90eb Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 21 Feb 2018 15:26:32 +0000 Subject: [PATCH 178/225] Disallow `@inheritDoc` and `{@inheritDoc}` tags We should explicitly define param tyypes, return type and thrown exceptions --- .../Sniffs/Commenting/DocCommentSniff.php | 23 +++++++++++++++++++ test/Sniffs/Commenting/DocCommentUnitTest.inc | 22 ++++++++++++++++++ .../Commenting/DocCommentUnitTest.inc.fixed | 22 ++++++++++++++++++ test/Sniffs/Commenting/DocCommentUnitTest.php | 4 ++++ 4 files changed, 71 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index 38a274db..d73cffb0 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -76,6 +76,7 @@ public function process(File $phpcsFile, $stackPtr) $this->checkAfterClose($phpcsFile, $commentStart, $commentEnd); $this->checkCommentIndents($phpcsFile, $commentStart, $commentEnd); $this->checkTagsSpaces($phpcsFile, $commentStart); + $this->checkInheritDoc($phpcsFile, $commentStart, $commentEnd); // Doc block comment in one line. if ($tokens[$commentStart]['line'] === $tokens[$commentEnd]['line']) { @@ -816,4 +817,26 @@ private function checkSpacesAfterTag(File $phpcsFile, int $tag) : void $phpcsFile->fixer->replaceToken($tag + 2, $expected); } } + + private function checkInheritDoc(File $phpcsFile, int $commentStart, int $commentEnd) : void + { + $tokens = $phpcsFile->getTokens(); + + $commentContent = $phpcsFile->getTokensAsString($commentStart + 1, $commentEnd - $commentStart - 1); + if (preg_match('/\*.*\{@inheritDoc\}/i', $commentContent, $m)) { + $error = 'Tag {@inheritDoc} is not allowed in doc-block comment. Please define explicitly types.'; + $phpcsFile->addError($error, $commentStart, 'InheritDoc'); + return; + } + + if (isset($tokens[$commentStart]['comment_tags'])) { + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if (strtolower($tokens[$tag]['content']) === '@inheritdoc') { + $error = 'Tag @inheritDoc is not allowed in doc-block comment. Please define explicitly types.'; + $phpcsFile->addError($error, $tag, 'InheritDocTag'); + break; + } + } + } + } } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc b/test/Sniffs/Commenting/DocCommentUnitTest.inc index 8949b845..1065f04c 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc @@ -219,4 +219,26 @@ class Foo * } */ private function twoLevelNesting(array $a) {} + + /** + * This is a description. + * {@inheritDoc} + */ + private function inheritDoc1() {} + + /** + * This is a description. + * {@inheritdoc} + */ + private function inheritDoc2() {} + + /** + * @inheritDoc + */ + private function inheritDocTag1() {} + + /** + * @inheritdoc + */ + private function inheritDocTag2() {} } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed index e4c1227b..a056d081 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed @@ -221,4 +221,26 @@ $c = 'xyz'; * } */ private function twoLevelNesting(array $a) {} + + /** + * This is a description. + * {@inheritDoc} + */ + private function inheritDoc1() {} + + /** + * This is a description. + * {@inheritdoc} + */ + private function inheritDoc2() {} + + /** + * @inheritDoc + */ + private function inheritDocTag1() {} + + /** + * @inheritdoc + */ + private function inheritDocTag2() {} } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.php b/test/Sniffs/Commenting/DocCommentUnitTest.php index a0939526..623e9289 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.php +++ b/test/Sniffs/Commenting/DocCommentUnitTest.php @@ -164,6 +164,10 @@ public function getErrorList($testFile = '') 216 => 1, 217 => 1, 218 => 1, + 223 => 1, + 229 => 1, + 236 => 1, + 241 => 1, ]; } From 4d11dfe7c932c2175b71fc1e09ea271b836ef11f Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 22 Feb 2018 08:29:24 +0000 Subject: [PATCH 179/225] InstantiatingParenthesis sniff fix on instantiating from array values --- .../Sniffs/PHP/InstantiatingParenthesisSniff.php | 5 +++++ test/Sniffs/PHP/InstantiatingParenthesisUnitTest.inc | 8 ++++++++ .../Sniffs/PHP/InstantiatingParenthesisUnitTest.inc.fixed | 8 ++++++++ test/Sniffs/PHP/InstantiatingParenthesisUnitTest.php | 3 +++ 4 files changed, 24 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php index c5fdaf0a..0d64da31 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/InstantiatingParenthesisSniff.php @@ -14,6 +14,7 @@ use const T_NEW; use const T_NS_SEPARATOR; use const T_OPEN_PARENTHESIS; +use const T_OPEN_SQUARE_BRACKET; use const T_SELF; use const T_STATIC; use const T_STRING; @@ -50,6 +51,10 @@ public function process(File $phpcsFile, $stackPtr) true ); + while ($tokens[$end]['code'] === T_OPEN_SQUARE_BRACKET) { + $end = $phpcsFile->findNext(Tokens::$emptyTokens, $tokens[$end]['bracket_closer'] + 1, null, true); + } + if ($tokens[$end]['code'] !== T_OPEN_PARENTHESIS) { $last = $phpcsFile->findPrevious( Tokens::$emptyTokens, diff --git a/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.inc b/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.inc index 5c27e8f4..ef462093 100644 --- a/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.inc +++ b/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.inc @@ -31,3 +31,11 @@ array(new DateTime); $anonymousClass = new class{}; $anonymousClass = new class {}; + +new $arr['val']; +new $arr['val'](); +(new $arr)['val']; +(new $arr())['val']; + +new $arr['abc']['def']; +new $arr['key']['inx'](); diff --git a/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.inc.fixed b/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.inc.fixed index 8437beb7..d1242638 100644 --- a/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.inc.fixed +++ b/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.inc.fixed @@ -31,3 +31,11 @@ array(new DateTime()); $anonymousClass = new class(){}; $anonymousClass = new class() {}; + +new $arr['val'](); +new $arr['val'](); +(new $arr())['val']; +(new $arr())['val']; + +new $arr['abc']['def'](); +new $arr['key']['inx'](); diff --git a/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.php b/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.php index a0c28d9a..fa32450a 100644 --- a/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.php +++ b/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.php @@ -28,6 +28,9 @@ public function getErrorList($testFile = '') 30 => 1, 32 => 1, 33 => 1, + 35 => 1, + 37 => 1, + 40 => 1, ]; } From dcc3497f751726c80a60e11a43034993886624ad Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 22 Feb 2018 08:36:32 +0000 Subject: [PATCH 180/225] Allow parenthesis after close square bracket --- .../Sniffs/Formatting/UnnecessaryParenthesesSniff.php | 10 ++++++++++ .../Formatting/UnnecessaryParenthesesUnitTest.inc | 2 ++ .../UnnecessaryParenthesesUnitTest.inc.fixed | 2 ++ 3 files changed, 14 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php index f7ebe2bd..00c9b9dd 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -53,10 +53,14 @@ class UnnecessaryParenthesesSniff implements Sniff { + /** + * @var int[] + */ private $parenthesesAllowedTokens = [ T_ANON_CLASS, T_CLOSE_CURLY_BRACKET, T_CLOSE_PARENTHESIS, + T_CLOSE_SQUARE_BRACKET, T_EMPTY, T_EVAL, T_EXIT, @@ -70,6 +74,9 @@ class UnnecessaryParenthesesSniff implements Sniff T_VARIABLE, ]; + /** + * @var int[] + */ private $endTokens = [ T_INLINE_ELSE, T_INLINE_THEN, @@ -85,6 +92,9 @@ class UnnecessaryParenthesesSniff implements Sniff T_CLOSE_TAG, ]; + /** + * @var int[] + */ private $spaceTokens = [ T_CLONE, T_ECHO, diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc index 7f167e0d..9351a2b6 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc @@ -157,5 +157,7 @@ class UnnecessaryParentheses $a = $b ? ($c ?? 1) : 0; $a = $b ? 0 : ($c ?? 1); + + new $arr['abc']['def'](); } } diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed index e4dc77d7..1f3d7dd7 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed @@ -157,5 +157,7 @@ class UnnecessaryParentheses $a = $b ? ($c ?? 1) : 0; $a = $b ? 0 : ($c ?? 1); + + new $arr['abc']['def'](); } } From bc891eb7ceb58460ea54047f109f409d553fd3cb Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Feb 2018 19:22:37 +0000 Subject: [PATCH 181/225] CorrectClassNameCase sniff fix for array values --- .../Sniffs/PHP/CorrectClassNameCaseSniff.php | 15 ++++++++++----- test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc | 7 +++++++ .../PHP/CorrectClassNameCaseUnitTest.inc.fixed | 7 +++++++ test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php | 1 + 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php index ce1edb1f..6f368561 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/CorrectClassNameCaseSniff.php @@ -22,7 +22,9 @@ use function preg_quote; use function preg_replace; use function strlen; +use function strstr; use function strtolower; +use function strtr; use function substr; use function trim; @@ -291,13 +293,16 @@ private function checkTag(File $phpcsFile, int $stackPtr) : void */ private function getExpectedName(File $phpcsFile, string $class, int $stackPtr) : string { + $suffix = strstr($class, '['); + $class = strtr($class, ['[' => '', ']' => '']); + if ($class[0] === '\\') { $result = $this->hasDifferentCase(ltrim($class, '\\')); if ($result) { - return '\\' . $result; + return '\\' . $result . $suffix; } - return $class; + return $class . $suffix; } $imports = $this->getGlobalUses($phpcsFile); @@ -305,7 +310,7 @@ private function getExpectedName(File $phpcsFile, string $class, int $stackPtr) // Check if class is imported. if (isset($imports[strtolower($class)])) { if ($imports[strtolower($class)]['alias'] !== $class) { - return $imports[strtolower($class)]['alias']; + return $imports[strtolower($class)]['alias'] . $suffix; } } else { // Class from the same namespace. @@ -314,11 +319,11 @@ private function getExpectedName(File $phpcsFile, string $class, int $stackPtr) $result = $this->hasDifferentCase(ltrim($fullClassName, '\\')); if ($result) { - return ltrim(substr($result, strlen($namespace)), '\\'); + return ltrim(substr($result, strlen($namespace)), '\\') . $suffix; } } - return $class; + return $class . $suffix; } /** diff --git a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc index 988ad229..7a769e3b 100644 --- a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc +++ b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc @@ -84,4 +84,11 @@ class MyClass ) : \zendcodingstandardtest\sniffs\testcase { throw new \RangeException; } + + /** + * @param iterable|\traversable[]|\arrayobject[]|foo[] $a + */ + public function trav(iterable $a) + { + } } diff --git a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc.fixed b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc.fixed index 258c69b1..8de5d407 100644 --- a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc.fixed +++ b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.inc.fixed @@ -84,4 +84,11 @@ class MyClass ) : \ZendCodingStandardTest\Sniffs\TestCase { throw new \RangeException; } + + /** + * @param iterable|\Traversable[]|\ArrayObject[]|Foo[] $a + */ + public function trav(iterable $a) + { + } } diff --git a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php index ad552e3d..68abb39a 100644 --- a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php +++ b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php @@ -57,6 +57,7 @@ public function getErrorList($testFile = '') 77 => 1, 83 => 1, 84 => 1, + 89 => 1, ]; } From 4bd129366a324e3a36716a86beb94a624e1e5fdd Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Feb 2018 19:25:20 +0000 Subject: [PATCH 182/225] TagCase sniff is fixable --- src/ZendCodingStandard/Sniffs/Commenting/TagCaseSniff.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/TagCaseSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/TagCaseSniff.php index 663eb1aa..3cd5a02a 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/TagCaseSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/TagCaseSniff.php @@ -115,6 +115,10 @@ public function process(File $phpcsFile, $stackPtr) $content, ]; - $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode, $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($stackPtr, $tagName); + } } } From c534e79111ad59403d5809ea8ff05f33fb64cbf2 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Feb 2018 19:47:33 +0000 Subject: [PATCH 183/225] New sniff - TagWithType - processing types with tags - `@param`, - `@return` - `@var` --- src/ZendCodingStandard/Helper/Methods.php | 34 +- .../Sniffs/Commenting/TagWithTypeSniff.php | 471 +++++++++++++++++ .../Sniffs/Functions/ParamSniff.php | 156 +----- .../Sniffs/Functions/ReturnTypeSniff.php | 242 ++------- .../Commenting/TagWithTypeUnitTest.1.inc | 299 +++++++++++ .../TagWithTypeUnitTest.1.inc.fixed | 299 +++++++++++ .../Commenting/TagWithTypeUnitTest.2.inc | 351 +++++++++++++ .../TagWithTypeUnitTest.2.inc.fixed | 351 +++++++++++++ .../Commenting/TagWithTypeUnitTest.3.inc | 287 +++++++++++ .../TagWithTypeUnitTest.3.inc.fixed | 287 +++++++++++ .../Sniffs/Commenting/TagWithTypeUnitTest.inc | 10 + .../Sniffs/Commenting/TagWithTypeUnitTest.php | 188 +++++++ test/Sniffs/Functions/ParamUnitTest.1.inc | 73 +-- test/Sniffs/Functions/ParamUnitTest.inc | 67 +-- test/Sniffs/Functions/ParamUnitTest.inc.fixed | 65 +-- test/Sniffs/Functions/ParamUnitTest.php | 110 ++-- .../Sniffs/Functions/ReturnTypeUnitTest.1.inc | 103 ---- .../Functions/ReturnTypeUnitTest.1.inc.fixed | 300 +++++++++++ .../Sniffs/Functions/ReturnTypeUnitTest.2.inc | 2 +- .../Functions/ReturnTypeUnitTest.2.inc.fixed | 473 ++++++++++++++++++ .../Sniffs/Functions/ReturnTypeUnitTest.3.inc | 84 +--- test/Sniffs/Functions/ReturnTypeUnitTest.inc | 134 +---- test/Sniffs/Functions/ReturnTypeUnitTest.php | 154 +++--- 23 files changed, 3591 insertions(+), 949 deletions(-) create mode 100644 src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php create mode 100644 test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc create mode 100644 test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc.fixed create mode 100644 test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc create mode 100644 test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc.fixed create mode 100644 test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc create mode 100644 test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc.fixed create mode 100644 test/Sniffs/Commenting/TagWithTypeUnitTest.inc create mode 100644 test/Sniffs/Commenting/TagWithTypeUnitTest.php create mode 100644 test/Sniffs/Functions/ReturnTypeUnitTest.1.inc.fixed create mode 100644 test/Sniffs/Functions/ReturnTypeUnitTest.2.inc.fixed diff --git a/src/ZendCodingStandard/Helper/Methods.php b/src/ZendCodingStandard/Helper/Methods.php index 956e1318..4c4d3c3b 100644 --- a/src/ZendCodingStandard/Helper/Methods.php +++ b/src/ZendCodingStandard/Helper/Methods.php @@ -16,6 +16,7 @@ use function in_array; use function key; use function ltrim; +use function preg_match; use function preg_replace; use function str_replace; use function strcmp; @@ -27,6 +28,7 @@ use const T_CLASS; use const T_DOC_COMMENT_CLOSE_TAG; +use const T_DOC_COMMENT_TAG; use const T_DOC_COMMENT_WHITESPACE; use const T_INTERFACE; use const T_TRAIT; @@ -142,8 +144,10 @@ private function initScope(File $phpcsFile, int $stackPtr) : void $tokens = $phpcsFile->getTokens(); - $this->methodName = $phpcsFile->getDeclarationName($stackPtr); - $this->isSpecialMethod = $this->methodName === '__construct' || $this->methodName === '__destruct'; + if ($tokens[$stackPtr]['code'] !== T_DOC_COMMENT_TAG) { + $this->methodName = $phpcsFile->getDeclarationName($stackPtr); + $this->isSpecialMethod = $this->methodName === '__construct' || $this->methodName === '__destruct'; + } // Get class name of the method, name of the parent class and implemented interfaces names $this->className = null; @@ -212,7 +216,7 @@ private function getSuggestedType(string $class) : string $suffix = strstr($class, '['); $clear = strtolower(strtr($class, ['?' => '', '[' => '', ']' => ''])); - if (in_array($clear, $this->simpleReturnTypes, true)) { + if (in_array($clear, $this->simpleReturnTypes + ['static' => 'static'], true)) { return $prefix . $clear . $suffix; } @@ -364,4 +368,28 @@ private function getCommentStart(File $phpcsFile, int $stackPtr) : ?int return $tokens[$commentEnd]['comment_opener']; } + + private function isThis(string $tag, string $type) : bool + { + if ($tag !== '@return') { + return false; + } + + return in_array(strtolower($type), ['$this', '$this|null', 'null|$this'], true); + } + + private function isVariable(string $str) : bool + { + return strpos($str, '$') === 0 + || strpos($str, '...$') === 0; + } + + private function isType(string $tag, string $type) : bool + { + if ($this->isThis($tag, $type)) { + return true; + } + + return (bool) preg_match('/^((?:\\\\?[a-z0-9]+)+(?:\[\])*)(\|(?:\\\\?[a-z0-9]+)+(?:\[\])*)*$/i', $type); + } } diff --git a/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php new file mode 100644 index 00000000..d237a86a --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php @@ -0,0 +1,471 @@ +initScope($phpcsFile, $stackPtr); + + $this->type = null; + $this->types = []; + $this->description = null; + + $tokens = $phpcsFile->getTokens(); + + $tag = strtolower($tokens[$stackPtr]['content']); + if (! in_array($tag, $this->tags, true)) { + return; + } + + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $stackPtr + 1); + if ($string !== $stackPtr + 2 + || $tokens[$string]['line'] !== $tokens[$stackPtr]['line'] + ) { + if ($tag === '@param') { + $error = 'Missing param type and name with tag %s'; + } else { + $error = 'Missing type with tag %s'; + } + $data = [$tag]; + $phpcsFile->addError($error, $stackPtr, 'MissingType', $data); + return; + } + + $split = preg_split('/\s/', $tokens[$stackPtr + 2]['content'], 3); + $this->type = array_shift($split); + $this->description = trim(array_shift($split) ?: '') ?: null; + + if ($tag === '@return' && ! $this->processReturnTag($phpcsFile, $stackPtr)) { + return; + } + + if ($tag === '@param' && ! $this->processParamTag($phpcsFile, $stackPtr)) { + return; + } + + if ($tag === '@var' && ! $this->processVarTag($phpcsFile, $stackPtr)) { + return; + } + + if (! $this->isType($tag, $this->type)) { + $error = 'Invalid type format with tag %s'; + $data = [$tag]; + $phpcsFile->addError($error, $stackPtr + 2, 'InvalidTypeFormat', $data); + return; + } + + if ($this->isThis($tag, $this->type) + && strtolower($this->type) !== $this->type + ) { + $error = 'Invalid case of type with tag %s; expected "%s" but found "%s"'; + $data = [ + $tag, + strtolower($this->type), + $this->type, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr + 2, 'InvalidThisCase', $data); + + if ($fix) { + $content = trim(strtolower($this->type) . ' ' . $this->description); + $phpcsFile->fixer->replaceToken($stackPtr + 2, $content); + } + } + + // Type with tag contains only null, null[], null[][], null|null[], ... + $cleared = array_unique(explode('|', strtolower(strtr($this->type, ['[' => '', ']' => ''])))); + if (count($cleared) === 1 && $cleared[0] === 'null') { + $error = 'Type with tag %s contains only "null". Please specify all possible types'; + $data = [ + $tag, + $this->type, + ]; + $phpcsFile->addError($error, $stackPtr + 2, 'OnlyNullType', $data); + return; + } + + $this->checkTypes($phpcsFile, $tag, $stackPtr); + } + + /** + * @return bool True if can continue further processing. + */ + private function processReturnTag(File $phpcsFile, int $tagPtr) : bool + { + if (strtolower($this->type) === 'void') { + if ($this->description) { + $error = 'Description for return "void" type is not allowed.' + . ' Please move it to method description.'; + $phpcsFile->addError($error, $tagPtr, 'ReturnVoidDescription'); + return false; + } + + $error = 'Return tag with "void" type is redundant.'; + $fix = $phpcsFile->addFixableError($error, $tagPtr, 'ReturnVoid'); + + if ($fix) { + $this->removeTag($phpcsFile, $tagPtr); + } + + return false; + } + + if (isset($this->description[0]) && $this->description[0] === '$') { + $error = 'Return tag description cannot start from variable name.'; + $phpcsFile->addError($error, $tagPtr + 2, 'ReturnVariable'); + } + + return true; + } + + private function processParamTag(File $phpcsFile, int $tagPtr) : bool + { + $tokens = $phpcsFile->getTokens(); + + $split = preg_split('/\s/', $tokens[$tagPtr + 2]['content'], 3); + + if (! isset($split[1])) { + if ($this->isVariable($split[0])) { + $error = 'Missing param type for param %s'; + $data = [ + $split[0], + ]; + $phpcsFile->addError($error, $tagPtr + 2, 'MissingParamType', $data); + } else { + $error = 'Missing parameter name in PHPDocs'; + $phpcsFile->addError($error, $tagPtr + 2, 'MissingParamName'); + } + + return false; + } + + if (! $this->isVariable($split[1])) { + $error = 'Invalid parameter name'; + $phpcsFile->addError($error, $tagPtr + 2, 'InvalidParamName'); + return false; + } + + return true; + } + + private function processVarTag(File $phpcsFile, int $tagPtr) : bool + { + $tokens = $phpcsFile->getTokens(); + + $nested = 0; + $commentStart = $phpcsFile->findPrevious(T_DOC_COMMENT_OPEN_TAG, $tagPtr - 1); + $i = $tagPtr; + while ($i = $phpcsFile->findPrevious(T_DOC_COMMENT_STRING, $i - 1, $commentStart)) { + if ($tokens[$i]['content'][0] === '}') { + --$nested; + } + + if (substr($tokens[$i]['content'], -1) === '{') { + ++$nested; + } + + $i = $phpcsFile->findPrevious([T_DOC_COMMENT_TAG, T_DOC_COMMENT_OPEN_TAG], $i - 1); + } + + $split = preg_split('/\s/', $tokens[$tagPtr + 2]['content'], 3); + if ($nested > 0) { + if (! empty($split[0][0]) && $split[0][0] === '$') { + $error = 'Missing variable type'; + $phpcsFile->addError($error, $tagPtr + 2, 'MissingVarType'); + + return false; + } + + if (empty($split[1]) || (! empty($split[1][0]) && $split[1][0] !== '$')) { + $error = 'Missing variable name'; + $phpcsFile->addError($error, $tagPtr + 2, 'MissingVarName'); + + return false; + } + + return true; + } + + if (! empty($split[0][0]) && $split[0][0] === '$') { + $error = 'Variable name should not be included in the tag'; + $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'VariableName'); + + if ($fix) { + unset($split[0]); + $content = trim(implode(' ', $split)); + if ($phpcsFile->getTokens()[$tagPtr + 3]['code'] !== T_DOC_COMMENT_WHITESPACE) { + $content .= ' '; + } + $phpcsFile->fixer->beginChangeset(); + if (trim($content) === '') { + $phpcsFile->fixer->replaceToken($tagPtr + 1, ''); + } + $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); + $phpcsFile->fixer->endChangeset(); + } + return false; + } + + if (! empty($split[1][0]) && $split[1][0] === '$') { + $error = 'Variable name should not be included in the tag'; + $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'VariableName'); + + if ($fix) { + unset($split[1]); + $phpcsFile->fixer->replaceToken($tagPtr + 2, implode(' ', $split)); + } + } + + return true; + } + + private function checkTypes(File $phpcsFile, string $tag, int $tagPtr) : void + { + $hasInvalidType = false; + $this->types = explode('|', $this->type); + + // Check if types are unique. + $uniq = array_unique($this->types); + if ($uniq !== $this->types) { + $expected = implode('|', $uniq); + $error = 'Duplicated types with tag; expected "%s", but found "%s"'; + $data = [ + $expected, + $this->type, + ]; + $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'DuplicateTypes', $data); + + if ($fix) { + $content = trim($expected . ' ' . $this->description); + $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); + } + + return; + } + + $count = count($this->types); + foreach ($this->types as $key => $type) { + $lower = strtolower($type); + + if ($count > 1 + && ($lower === 'mixed' || strpos($lower, 'mixed[') === 0) + ) { + $error = 'Type %s cannot be mixed with other types.'; + $data = [ + $type, + ]; + $phpcsFile->addError($error, $tagPtr + 2, 'TypeMixed', $data); + + $hasInvalidType = true; + continue; + } + + $clearType = strtr($lower, ['[' => '', ']' => '']); + if ($tag === '@param' || $tag === '@var') { + if (in_array($clearType, ['void', 'true', 'false'], true)) { + $error = 'Invalid param type: "%s"'; + $code = sprintf('InvalidType%s', ucfirst($clearType)); + $data = [ + $type, + ]; + $phpcsFile->addError($error, $tagPtr + 2, $code, $data); + + $hasInvalidType = true; + continue; + } + } + + // todo: what with void[] ? + if ($clearType === 'void') { + // If void is mixed up with other return types. + $error = 'Type "void" is mixed with other types.'; + $phpcsFile->addError($error, $tagPtr + 2, 'VoidMixed'); + + $hasInvalidType = true; + continue; + } + + if (in_array(strtolower($type), ['null', 'true', 'false'], true)) { + $suggestedType = strtolower($type); + } else { + $suggestedType = $this->getSuggestedType($type); + } + if ($suggestedType !== $type) { + if (strpos($suggestedType, 'self') === 0 + && strtolower($type) !== $suggestedType + ) { + if ($tag === '@param' || $tag === '@var') { + $error = 'The type cannot be class name. Please use "self" or "static" instead'; + } else { + $error = 'Return type cannot be class name. Please use "self", "static" or "$this" instead' + . ' depends what you expect to be returned'; + } + $phpcsFile->addError($error, $tagPtr + 2, 'InvalidReturnClassName'); + + $hasInvalidType = true; + continue; + } + + $error = 'Invalid type with tag; expected "%s", but found "%s"'; + $data = [ + $suggestedType, + $type, + ]; + $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'InvalidType', $data); + + if ($fix) { + $this->types[$key] = $suggestedType; + $content = trim(implode('|', $this->types) . ' ' . $this->description); + if ($phpcsFile->getTokens()[$tagPtr + 3]['code'] !== T_DOC_COMMENT_WHITESPACE) { + $content .= ' '; + } + $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); + } + + $hasInvalidType = true; + continue; + } + } + + if ($hasInvalidType) { + return; + } + + // Check boolean values with tag + $lowerReturnDocTypes = explode('|', strtolower($this->type)); + $hasTrue = in_array('true', $lowerReturnDocTypes, true); + $hasFalse = in_array('false', $lowerReturnDocTypes, true); + if (in_array('bool', $lowerReturnDocTypes, true)) { + if ($hasTrue) { + $error = 'Type with tag contains "bool" and "true". Please use just "bool"'; + $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'BoolAndTrue'); + + if ($fix) { + $types = array_filter($this->types, function ($v) { + return strtolower($v) !== 'true'; + }); + $content = trim(implode('|', $types) . ' ' . $this->description); + $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); + } + + return; + } + + if ($hasFalse) { + $error = 'Type with tag contains "bool" and "false". Please use just "bool"'; + $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'BoolAndFalse'); + + if ($fix) { + $types = array_filter($this->types, function ($v) { + return strtolower($v) !== 'false'; + }); + $content = trim(implode('|', $types) . ' ' . $this->description); + $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); + } + + return; + } + } elseif ($hasTrue && $hasFalse) { + $error = 'Return tag contains "true" and "false". Please use "bool" instead.'; + $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'TrueAndFalse'); + + if ($fix) { + $types = array_filter($this->types, function ($v) { + return ! in_array(strtolower($v), ['true', 'false'], true); + }); + $types[] = 'bool'; + $content = trim(implode('|', $types) . ' ' . $this->description); + $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); + } + + return; + } + + // todo: here was previously uniqueness check + + // Check if order of types is as expected: first null, then simple types, and then complex. + usort($this->types, function ($a, $b) { + return $this->sortTypes($a, $b); + }); + $content = implode('|', $this->types); + if ($content !== $this->type) { + $error = 'Invalid order of types with tag; expected "%s" but found "%s"'; + $data = [ + $content, + $this->type, + ]; + $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'InvalidOrder', $data); + + if ($fix) { + $content = trim($content . ' ' . $this->description); + $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); + } + } + } +} diff --git a/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php index 977f6a4c..fadc9b6b 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ParamSniff.php @@ -10,7 +10,6 @@ use function array_filter; use function array_merge; -use function array_unique; use function count; use function current; use function explode; @@ -18,17 +17,11 @@ use function in_array; use function key; use function preg_grep; -use function preg_match; +use function preg_replace; use function preg_split; -use function sprintf; -use function str_replace; -use function stripos; use function strpos; use function strtolower; -use function strtr; use function trim; -use function ucfirst; -use function usort; use const T_ARRAY_HINT; use const T_CALLABLE; @@ -93,38 +86,23 @@ private function processParamDoc(File $phpcsFile, int $commentStart) : void continue; } - if ($tokens[$tag + 2]['code'] !== T_DOC_COMMENT_STRING) { - $error = 'Param type ane name missing for @param tag in function comment'; - $phpcsFile->addError($error, $tag, 'MissingParamDetailsDoc'); - + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag + 1); + if ($string !== $tag + 2 + || $tokens[$string]['line'] !== $tokens[$tag]['line'] + ) { + // Missing param type and name continue; } $split = preg_split('/\s/', $tokens[$tag + 2]['content'], 3); - - if (! isset($split[1])) { - if ($this->isVariable($split[0])) { - $error = 'Missing param type for param %s'; - $data = [ - $split[0], - ]; - $phpcsFile->addError($error, $tag + 2, 'MissingParamTypeDoc', $data); - } else { - $error = 'Missing parameter name in PHPDOcs'; - $phpcsFile->addError($error, $tag + 2, 'MissingParamNameDoc'); - } - + if (! isset($split[1]) || ! $this->isVariable($split[1])) { + // Missing param type or it's not a variable continue; } - if (! $this->isVariable($split[1])) { - $error = 'Invalid parameter name'; - $phpcsFile->addError($error, $tag + 2, 'InvalidParamNameDoc'); - continue; - } $name = $split[1]; - $clearName = strtolower(str_replace('.', '', $name)); + $clearName = strtolower(preg_replace('/^\.{3}/', '', $name)); if (in_array($clearName, $params, true)) { $error = 'Param tag is duplicated for parameter %s'; $data = [ @@ -152,12 +130,8 @@ private function processParamDoc(File $phpcsFile, int $commentStart) : void $this->processedParams[] = key($param); $paramsMap[key($param)] = ['token' => $tag, 'name' => $name]; - if (! $this->isType($split[0])) { - $error = 'Invalid type for param %s'; - $data = [ - $split[1], - ]; - $phpcsFile->addError($error, $tag + 2, 'InvalidParamTypeDoc', $data); + if (! $this->isType('@param', $split[0])) { + // The type definition is invalid continue; } $description = $split[2] ?? null; @@ -310,7 +284,7 @@ private function checkParam( return; } - $clearName = str_replace('.', '', $name); + $clearName = preg_replace('/^\.{3}/', '', $name); $isVariadic = $name !== $clearName; if ($param['name'] !== $clearName) { @@ -330,25 +304,6 @@ private function checkParam( $types = explode('|', $typeStr); - // Check if types are unique. - $uniq = array_unique($types); - if ($uniq !== $types) { - $expected = implode('|', $uniq); - $error = 'Duplicated types in param tag; expected "%s", but found "%s"'; - $data = [ - $expected, - implode('|', $types), - ]; - $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'DuplicateParamDocTypes', $data); - - if ($fix) { - $content = trim($expected . ' ' . $name . ' ' . $description); - $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); - } - - return; - } - // Check if null is one of the types if (($param['nullable_type'] || (isset($param['default']) && strtolower($param['default']) === 'null')) @@ -393,62 +348,6 @@ private function checkParam( continue; } - if (stripos($type, 'null[') === 0) { - $error = 'Param type "%s" is not a valid type'; - $data = [ - $type, - ]; - $phpcsFile->addError($error, $tagPtr + 2, 'ParamDocNullArray', $data); - - $break = true; - continue; - } - - if ($count > 1 - && ($lower === 'mixed' || strpos($lower, 'mixed[') === 0) - ) { - $error = 'Param type "%s" cannot be mixed with other types.'; - $data = [ - $type, - ]; - $phpcsFile->addError($error, $tagPtr + 2, 'ParamDocMixed', $data); - - $break = true; - continue; - } - - $clearType = strtr($lower, ['[' => '', ']' => '']); - if (in_array($clearType, ['void', 'true', 'false'], true)) { - $error = 'Invalid param type: "%s"'; - $code = sprintf('InvalidParam%sType', ucfirst($clearType)); - $data = [ - $type, - ]; - $phpcsFile->addError($error, $tagPtr + 2, $code, $data); - - $break = true; - continue; - } - - $suggestedType = $this->getSuggestedType($type); - if ($suggestedType !== $type) { - $error = 'Invalid param type; expected "%s", but found "%s"'; - $data = [ - $suggestedType, - $type, - ]; - $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'InvalidParamDocType', $data); - - if ($fix) { - $types[$key] = $suggestedType; - $content = trim(implode('|', $types) . ' ' . $name . ' ' . $description); - $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); - } - - $break = true; - continue; - } - if ($typeHint) { $simpleTypes = array_merge($this->simpleReturnTypes, ['mixed']); @@ -564,26 +463,6 @@ private function checkParam( return; } - // Check if order of return types is as expected: first null, then simple types, and then complex. - $unsorted = implode('|', $types); - usort($types, function ($a, $b) { - return $this->sortTypes($a, $b); - }); - $content = implode('|', $types); - if ($content !== $unsorted) { - $error = 'Invalid order of param types in @param tag; expected "%s" but found "%s"'; - $data = [ - $content, - $unsorted, - ]; - $fix = $phpcsFile->addFixableError($error, $tagPtr + 2, 'ReturnTypesOrder', $data); - - if ($fix) { - $content = trim($content . ' ' . $name . ' ' . $description); - $phpcsFile->fixer->replaceToken($tagPtr + 2, $content); - } - } - // Check if PHPDocs param is required if ($typeHint && ! $description) { $tmpTypeHint = $typeHint; @@ -605,17 +484,6 @@ private function checkParam( } } - private function isVariable(string $str) : bool - { - return strpos($str, '$') === 0 - || strpos($str, '...$') === 0; - } - - private function isType(string $str) : bool - { - return (bool) preg_match('/^((?:\\\\?[a-z0-9]+)+(?:\[\])*)(\|(?:\\\\?[a-z0-9]+)+(?:\[\])*)*$/i', $str); - } - private function processParamSpec(File $phpcsFile) : void { foreach ($this->params as $k => $param) { diff --git a/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php index 95dc5274..6ef69c56 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ReturnTypeSniff.php @@ -20,7 +20,6 @@ use function implode; use function in_array; use function preg_grep; -use function preg_match; use function preg_replace; use function preg_split; use function sprintf; @@ -29,8 +28,6 @@ use function strtolower; use function strtr; use function trim; -use function ucfirst; -use function usort; use const T_ANON_CLASS; use const T_ARRAY; @@ -76,14 +73,44 @@ class ReturnTypeSniff implements Sniff { use Methods; + /** + * @var string + */ private $returnDoc; + + /** + * @var array + */ private $returnDocTypes = []; + + /** + * @var string + */ private $returnDocValue; + + /** + * @var null|string + */ private $returnDocDescription; + + /** + * @var bool + */ private $returnDocIsValid = true; + /** + * @var string + */ private $returnType; + + /** + * @var string + */ private $returnTypeValue; + + /** + * @var bool + */ private $returnTypeIsValid = true; /** @@ -158,10 +185,10 @@ private function processReturnDoc(File $phpcsFile, int $commentStart) : void $phpcsFile->addError($error, $tag, 'SpecialMethodReturnTag'); } - if ($tokens[$tag + 2]['code'] !== T_DOC_COMMENT_STRING) { - $error = 'Return type missing for @return tag in function comment'; - $phpcsFile->addError($error, $tag, 'MissingReturnTypeDoc'); - + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag + 1); + if ($string !== $tag + 2 + || $tokens[$string]['line'] !== $tokens[$tag]['line'] + ) { $this->returnDoc = $tag; $this->returnDocIsValid = false; return; @@ -181,222 +208,23 @@ private function processReturnDoc(File $phpcsFile, int $commentStart) : void $this->returnDocDescription = isset($split[1]) ? trim($split[1]) : null; if (strtolower($this->returnDocValue) === 'void') { - if ($this->returnDocDescription) { - $error = 'Description for return "void" type is not allowed.' - . 'Please move it to method description.'; - $phpcsFile->addError($error, $returnDoc, 'ReturnVoidDescription'); - - $this->returnDocIsValid = false; - return; - } - - $error = 'Return tag "void" is redundant.'; - $fix = $phpcsFile->addFixableError($error, $returnDoc, 'ReturnVoid'); - - if ($fix) { - $this->removeTag($phpcsFile, $returnDoc); - } - $this->returnDocIsValid = false; return; } - $isThis = in_array(strtolower($this->returnDocValue), ['$this', '$this|null', 'null|$this'], true); - if (! $isThis - && ! preg_match( - '/^((?:\\\\?[a-z0-9]+)+(?:\[\])*)(\|(?:\\\\?[a-z0-9]+)+(?:\[\])*)*$/i', - $this->returnDocValue - ) - ) { - $error = 'Return type has invalid format'; - $phpcsFile->addError($error, $returnDoc + 2, 'ReturnInvalidFormat'); - + if (! $this->isType('@return', $this->returnDocValue)) { $this->returnDocIsValid = false; return; } - if ($isThis - && strtolower($this->returnDocValue) !== $this->returnDocValue - ) { - $error = 'Invalid case of return type; expected %s but found %s'; - $data = [ - '$this', - $this->returnDocValue, - ]; - $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'InvalidReturnThis', $data); - - if ($fix) { - $content = trim(strtolower($this->returnDocValue) . ' ' . $this->returnDocDescription); - $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); - } - } - // Return tag contains only null, null[], null[][], ... $cleared = strtolower(strtr($this->returnDocValue, ['[' => '', ']' => ''])); if ($cleared === 'null') { - $error = 'Return tag contains only "null". Please specify all returned types'; - $data = [ - $this->returnDocValue, - ]; - $code = sprintf('ReturnOnly%s', ucfirst($cleared)); - $phpcsFile->addError($error, $returnDoc + 2, $code, $data); - $this->returnDocIsValid = false; return; } - $hasInvalidType = false; $this->returnDocTypes = explode('|', $this->returnDocValue); - $count = count($this->returnDocTypes); - foreach ($this->returnDocTypes as $key => $type) { - $lower = strtolower($type); - - if ($count > 1 - && ($lower === 'mixed' || strpos($lower, 'mixed[') === 0) - ) { - $error = 'Return type %s cannot be mixed with other types.'; - $data = [ - $type, - ]; - $phpcsFile->addError($error, $returnDoc + 2, 'ReturnMixed', $data); - - $hasInvalidType = true; - continue; - } - - if ($lower === 'void') { - // If void is mixed up with other return types. - $error = 'Return "void" is mixed with other types. Please use null instead.'; - $phpcsFile->addError($error, $returnDoc + 2, 'ReturnVoidWithOther'); - - $hasInvalidType = true; - continue; - } - - if (in_array(strtolower($type), ['null', 'true', 'false'], true)) { - $suggestedType = strtolower($type); - } else { - $suggestedType = $this->getSuggestedType($type); - } - if ($suggestedType !== $type) { - if (strpos($suggestedType, 'self') === 0) { - $error = 'Return type cannot be class name. Please use "self", "static" or "$this" instead' - . ' depends what you expect to be returned'; - $phpcsFile->addError($error, $returnDoc + 2, 'InvalidReturnClassName'); - - $hasInvalidType = true; - continue; - } - - $error = 'Invalid return type; expected "%s", but found "%s"'; - $data = [ - $suggestedType, - $type, - ]; - $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'InvalidReturn', $data); - - if ($fix) { - $this->returnDocTypes[$key] = $suggestedType; - $content = trim(implode('|', $this->returnDocTypes) . ' ' . $this->returnDocDescription); - $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); - } - - $hasInvalidType = true; - continue; - } - } - - if ($hasInvalidType) { - return; - } - - // Check boolean values in return tag - $lowerReturnDocTypes = explode('|', strtolower($this->returnDocValue)); - $hasTrue = in_array('true', $lowerReturnDocTypes, true); - $hasFalse = in_array('false', $lowerReturnDocTypes, true); - if (in_array('bool', $lowerReturnDocTypes, true)) { - if ($hasTrue) { - $error = 'Return tag contains "bool" and "true". Please use just "bool"'; - $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'ReturnBoolAndTrue'); - - if ($fix) { - $types = array_filter($this->returnDocTypes, function ($v) { - return strtolower($v) !== 'true'; - }); - $content = trim(implode('|', $types) . ' ' . $this->returnDocDescription); - $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); - } - - return; - } - - if ($hasFalse) { - $error = 'Return tag contains "bool" and "false". Please use just "bool"'; - $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'ReturnBoolAndFalse'); - - if ($fix) { - $types = array_filter($this->returnDocTypes, function ($v) { - return strtolower($v) !== 'false'; - }); - $content = trim(implode('|', $types) . ' ' . $this->returnDocDescription); - $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); - } - - return; - } - } elseif ($hasTrue && $hasFalse) { - $error = 'Return tag contains "true" and "false". Please use "bool" instead.'; - $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'ReturnTrueAndFalse'); - - if ($fix) { - $types = array_filter($this->returnDocTypes, function ($v) { - return ! in_array(strtolower($v), ['true', 'false'], true); - }); - $types[] = 'bool'; - $content = trim(implode('|', $types) . ' ' . $this->returnDocDescription); - $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); - } - - return; - } - - // Check if types are unique. - $uniq = array_unique($this->returnDocTypes); - if ($uniq !== $this->returnDocTypes) { - $expected = implode('|', $uniq); - $error = 'Duplicated types in return tag; expected "%s", but found "%s"'; - $data = [ - $expected, - $this->returnDocValue, - ]; - $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'DuplicateReturnDocTypes', $data); - - if ($fix) { - $content = trim($expected . ' ' . $this->returnDocDescription); - $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); - } - - return; - } - - // Check if order of return types is as expected: first null, then simple types, and then complex. - usort($this->returnDocTypes, function ($a, $b) { - return $this->sortTypes($a, $b); - }); - $content = implode('|', $this->returnDocTypes); - if ($content !== $this->returnDocValue) { - $error = 'Invalid order of return types in @return tag; expected "%s" but found "%s"'; - $data = [ - $content, - $this->returnDocValue, - ]; - $fix = $phpcsFile->addFixableError($error, $returnDoc + 2, 'ReturnTypesOrder', $data); - - if ($fix) { - $content = trim($content . ' ' . $this->returnDocDescription); - $phpcsFile->fixer->replaceToken($returnDoc + 2, $content); - } - } } private function processReturnType(File $phpcsFile, int $stackPtr) : void diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc b/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc new file mode 100644 index 00000000..d354e040 --- /dev/null +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc @@ -0,0 +1,299 @@ + 1, + 17 => 1, + 22 => 1, + 27 => 1, + 32 => 1, + 47 => 2, + 52 => 1, + 57 => 1, + 62 => 1, + 67 => 1, + 72 => 1, + 77 => 1, + 82 => 1, + 87 => 1, + 92 => 1, + 107 => 1, + 112 => 1, + 117 => 1, + 122 => 2, + 127 => 1, + 132 => 1, + 137 => 1, + 142 => 1, + 147 => 1, + 152 => 1, + 157 => 1, + 162 => 1, + 167 => 1, + 172 => 1, + 177 => 1, + 182 => 1, + 187 => 1, + 192 => 1, + 202 => 1, + 207 => 1, + 212 => 1, + 217 => 1, + 222 => 1, + 227 => 1, + 232 => 1, + 237 => 1, + 242 => 1, + 252 => 1, + 272 => 1, + 277 => 1, + 282 => 1, + ]; + case 'TagWithTypeUnitTest.2.inc': + return [ + 12 => 1, + 22 => 1, + 27 => 1, + 32 => 1, + 47 => 2, + 52 => 1, + 57 => 1, + 62 => 1, + 67 => 1, + 72 => 1, + 77 => 1, + 82 => 1, + 87 => 1, + 92 => 1, + 107 => 1, + 112 => 1, + 117 => 1, + 122 => 1, + 127 => 1, + 132 => 1, + 137 => 1, + 142 => 1, + 147 => 1, + 152 => 1, + 157 => 1, + 162 => 1, + 167 => 1, + 172 => 1, + 177 => 1, + 182 => 1, + 187 => 1, + 202 => 1, + 207 => 1, + 212 => 2, + 222 => 1, + 227 => 1, + 232 => 1, + 237 => 1, + 242 => 1, + 247 => 1, + 252 => 1, + 257 => 1, + 262 => 1, + 267 => 1, + 277 => 1, + 282 => 1, + 287 => 1, + 292 => 1, + 297 => 2, + 302 => 2, + 307 => 1, + 327 => 1, + 332 => 1, + 337 => 1, + ]; + case 'TagWithTypeUnitTest.3.inc': + return [ + 12 => 1, + 22 => 1, + 27 => 1, + 32 => 1, + 47 => 2, + 52 => 1, + 57 => 1, + 62 => 1, + 67 => 1, + 72 => 1, + 77 => 1, + 82 => 1, + 87 => 1, + 92 => 1, + 107 => 1, + 112 => 1, + 117 => 1, + 122 => 2, + 127 => 1, + 132 => 1, + 137 => 1, + 142 => 1, + 147 => 1, + 152 => 1, + 157 => 1, + 162 => 1, + 167 => 1, + 172 => 1, + 177 => 1, + 182 => 1, + 192 => 1, + 197 => 1, + 202 => 1, + 207 => 1, + 212 => 1, + 217 => 1, + 222 => 1, + 227 => 1, + 232 => 1, + 242 => 1, + 255 => 1, + 258 => 1, + 261 => 1, + 265 => 1, + 269 => 1, + 272 => 1, + 281 => 1, + 282 => 1, + ]; + } + + return []; + } + + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') + { + return []; + } +} diff --git a/test/Sniffs/Functions/ParamUnitTest.1.inc b/test/Sniffs/Functions/ParamUnitTest.1.inc index 766c4b8a..0525d05d 100644 --- a/test/Sniffs/Functions/ParamUnitTest.1.inc +++ b/test/Sniffs/Functions/ParamUnitTest.1.inc @@ -7,112 +7,97 @@ class FunctionParam /** * @param mixed $x */ - public function test1($x) {} - - /** - * @param mixed[] $x - */ - public function test2($x) {} - - /** - * @param mixed|mixed[] $x - */ - public function test3($x) {} - - /** - * @param mixed $x - */ - public function test4(int $x) {} + public function test(int $x) {} /** * @param mixed $x */ - public function test5(MyObj $x) {} + public function test(MyObj $x) {} /** * @param mixed[] $x */ - public function test6(MyObj $x) {} + public function test(MyObj $x) {} /** * @param mixed $x */ - public function test7(\Generator $x) {} + public function test(\Generator $x) {} /** * @param mixed[] $x */ - public function test8(\Generator $x) {} + public function test(\Generator $x) {} /** * @param int $x */ - public function test9(\Generator $x) {} + public function test(\Generator $x) {} /** * @param MyObj $x */ - public function test10(\Generator $x) {} + public function test(\Generator $x) {} /** * @param mixed $x */ - public function test11(\Traversable $x) {} + public function test(\Traversable $x) {} /** * @param mixed[] $x */ - public function test12(\Traversable $x) {} + public function test(\Traversable $x) {} /** * @param int $x */ - public function test13(\Traversable $x) {} + public function test(\Traversable $x) {} /** * @param MyObj $x */ - public function test14(\Traversable $x) {} + public function test(\Traversable $x) {} /** * @param mixed $x */ - public function test15(iterable $x) {} + public function test(iterable $x) {} /** * @param mixed[] $x */ - public function test16(iterable $x) {} + public function test(iterable $x) {} /** * @param int $x */ - public function test17(iterable $x) {} + public function test(iterable $x) {} /** * @param MyObj $x */ - public function test18(iterable $x) {} + public function test(iterable $x) {} /** * @param mixed $x */ - public function test19(array $x) {} + public function test(array $x) {} /** * @param mixed[] $x */ - public function test20(array $x) {} + public function test(array $x) {} /** * @param int $x */ - public function test21(array $x) {} + public function test(array $x) {} /** * @param MyObj $x */ - public function test22(array $x) {} + public function test(array $x) {} /** * @param array|callable $a @@ -133,4 +118,24 @@ class FunctionParam * @param float|\Generator $a */ public function paramGeneratorWithOtherTypes($a) {} + + /** + * @param + */ + public function missingParamTypeAndName() {}; + + /** + * @param $a + */ + public function missingParamType($a) {} + + /** + * @param int + */ + public function missingParamName($a) {} + + /** + * @param int,string $a + */ + public function invalidType($a); } diff --git a/test/Sniffs/Functions/ParamUnitTest.inc b/test/Sniffs/Functions/ParamUnitTest.inc index eb3fea23..985f727e 100644 --- a/test/Sniffs/Functions/ParamUnitTest.inc +++ b/test/Sniffs/Functions/ParamUnitTest.inc @@ -104,28 +104,11 @@ class FunctionParam extends FunctionParamParent */ public function variadicParamWrongTag2(array ...$a) {} - /** - * @param - */ - public function missingParamTypeAndInvalidTypeHintCase(String $a) {} - - /** - * @param something - */ - public function invalidParamTagAndInvalidTypeHintCase(?INT $a) {} + public function invalidTypeHintCase1(String $a) {} - /** - * @param $a something - */ - public function invalidParamTag(bool $a) {} + public function invalidTypeHintCase2(?INT $a) {} /** - * @param ...$a - */ - public function missingTypeInParam(...$a) {} - - /** - * @param $c * @param int $inconsistentPARAMname */ public function inconsistentParamName($a, $inconsistentParamName) {} @@ -139,23 +122,6 @@ class FunctionParam extends FunctionParamParent public function nullableSelfAndParent(?FunctionParam $a, ?FunctionParamParent $b) {} - /** - * @param FunctionParam $a - * @param FunctionParamParent $b - */ - public function selfAndParentInTags($a, $b) {} - - /** - * @param bool|int|bool $a - */ - public function duplicatedTypeInTag($a) {} - - /** - * @param void $a - * @param false|true $b - */ - public function voidAndTrueAndFalse($a, $b) {} - /** * @param DateTime $a * @param \DateTime $b @@ -184,18 +150,8 @@ class FunctionParam extends FunctionParamParent public function selfInsteadOfClassName(\MyNamespace\Test\FunctionParam $a) {} - /** - * @param \MyNamespace\Test\FunctionParam $a - */ - public function selfInsteadOfClassNameInTag($a) {} - public function parentInsteadOfFCQNParentClassName(\ZTest\MyNamespace\ParentClass $b) {} - /** - * @param \ZTest\MyNamespace\ParentClass $a - */ - public function parentInsteadOfFCQNParentClassNameInTag($a) {} - /** * @param \DateTime $a Description. * @param null|DateTime ...$b @@ -216,20 +172,18 @@ class FunctionParam extends FunctionParamParent public function inconsistentPrimitiveTypes(int $a, bool $b, string $c) {} /** - * @param ?array $a - * @param |int| $b * @param int $c */ - public function invalidParamTypes($a, $b) {} + public function invalidParamDoc() {} /** * @param string $a - * @param \RuntimeException $b + * @param Exception $b */ public function wrongType(DateTime $a, \Throwable $b) {} /** - * @param String $a + * @param string $a * @param array $b * @param \Traversable $c * @param iterable $d @@ -242,14 +196,7 @@ class FunctionParam extends FunctionParamParent public function paramContainAnotherType(\DateTimeInterface $a) {} /** - * @param string|int|float $a - * @param DateTime|int|bool $b - * @param \ArrayObject|\ArrayAccess|DateTime|null $c - */ - public function wrongOrderOfParamTypes($a, $b, $c) {} - - /** - * @param boolean $a + * @param bool $a * @param null|DateTime|Something $b * @param string|DateTime|Something $c * @param null|DateTime $d @@ -268,7 +215,7 @@ class FunctionParam extends FunctionParamParent ) {} /** - * @param null[]|string[] $a + * @param string[] $a * @param null|int $b * @param int|string $c */ diff --git a/test/Sniffs/Functions/ParamUnitTest.inc.fixed b/test/Sniffs/Functions/ParamUnitTest.inc.fixed index fb352994..ec7ff2dc 100644 --- a/test/Sniffs/Functions/ParamUnitTest.inc.fixed +++ b/test/Sniffs/Functions/ParamUnitTest.inc.fixed @@ -47,7 +47,7 @@ class FunctionParam extends FunctionParamParent public function traversableSpecified(\Traversable $a) {} /** - * @param string|DateTime[]|\Traversable $a + * @param string|\DateTime[]|\Traversable $a */ public function traversableSpecifiedWrongly(\Traversable $a) {} @@ -104,28 +104,11 @@ class FunctionParam extends FunctionParamParent */ public function variadicParamWrongTag2(array ...$a) {} - /** - * @param - */ - public function missingParamTypeAndInvalidTypeHintCase(string $a) {} - - /** - * @param something - */ - public function invalidParamTagAndInvalidTypeHintCase(?int $a) {} + public function invalidTypeHintCase1(string $a) {} - /** - * @param $a something - */ - public function invalidParamTag(bool $a) {} + public function invalidTypeHintCase2(?int $a) {} /** - * @param ...$a - */ - public function missingTypeInParam(...$a) {} - - /** - * @param $c * @param int $inconsistentPARAMname */ public function inconsistentParamName($a, $inconsistentParamName) {} @@ -139,23 +122,6 @@ class FunctionParam extends FunctionParamParent public function nullableSelfAndParent(?self $a, ?parent $b) {} - /** - * @param self $a - * @param parent $b - */ - public function selfAndParentInTags($a, $b) {} - - /** - * @param bool|int $a - */ - public function duplicatedTypeInTag($a) {} - - /** - * @param void $a - * @param false|true $b - */ - public function voidAndTrueAndFalse($a, $b) {} - /** * * @@ -184,20 +150,10 @@ class FunctionParam extends FunctionParamParent public function selfInsteadOfClassName(self $a) {} - /** - * @param self $a - */ - public function selfInsteadOfClassNameInTag($a) {} - public function parentInsteadOfFCQNParentClassName(parent $b) {} /** - * @param parent $a - */ - public function parentInsteadOfFCQNParentClassNameInTag($a) {} - - /** - * @param DateTime $a Description. + * @param \DateTime $a Description. * */ public function canUseImportedClasses(DateTime $a, ?DateTime ...$b) {} @@ -216,11 +172,9 @@ class FunctionParam extends FunctionParamParent public function inconsistentPrimitiveTypes(int $a, bool $b, string $c) {} /** - * @param ?array $a - * @param |int| $b * @param int $c */ - public function invalidParamTypes($a, $b) {} + public function invalidParamDoc() {} /** * @param string $a @@ -241,13 +195,6 @@ class FunctionParam extends FunctionParamParent */ public function paramContainAnotherType(\DateTimeInterface $a) {} - /** - * @param float|int|string $a - * @param bool|int|DateTime $b - * @param null|\ArrayAccess|\ArrayObject|DateTime $c - */ - public function wrongOrderOfParamTypes($a, $b, $c) {} - /** * @param bool $a * @param null|DateTime|Something $b @@ -268,7 +215,7 @@ class FunctionParam extends FunctionParamParent ) {} /** - * @param null[]|string[] $a + * @param string[] $a * * @param int|string $c */ diff --git a/test/Sniffs/Functions/ParamUnitTest.php b/test/Sniffs/Functions/ParamUnitTest.php index df1c8f9d..25f611b0 100644 --- a/test/Sniffs/Functions/ParamUnitTest.php +++ b/test/Sniffs/Functions/ParamUnitTest.php @@ -17,93 +17,71 @@ public function getErrorList($testFile = '') switch ($testFile) { case 'ParamUnitTest.1.inc': return [ - 18 => 2, + 8 => 1, + 13 => 1, + 18 => 1, 23 => 1, - 28 => 1, 33 => 1, - 38 => 1, - 48 => 1, - 58 => 1, - 68 => 1, - 78 => 1, - 88 => 1, + 43 => 1, + 53 => 1, + 63 => 1, + 73 => 1, + 83 => 1, + 93 => 1, 98 => 1, - 108 => 1, - 113 => 1, + 130 => 1, + 135 => 1, ]; } return [ 18 => 1, 33 => 1, - 50 => 2, + 50 => 1, 67 => 1, 81 => 1, 85 => 3, 93 => 1, 98 => 1, - 108 => 1, - 110 => 1, - 113 => 1, - 115 => 1, - 118 => 1, - 123 => 1, - 125 => 1, + 107 => 1, + 109 => 1, + 112 => 1, + 114 => 1, + 117 => 1, + 121 => 2, + 123 => 2, + 126 => 1, + 127 => 1, 128 => 1, 129 => 1, + 130 => 1, 131 => 1, - 134 => 1, - 138 => 2, - 140 => 2, + 132 => 1, + 133 => 1, + 138 => 1, + 139 => 1, + 142 => 1, 143 => 1, - 144 => 1, - 149 => 1, - 154 => 1, - 155 => 2, - 160 => 1, - 161 => 1, - 162 => 1, + 147 => 1, + 151 => 1, + 153 => 1, + 157 => 1, + 159 => 2, 163 => 1, - 164 => 1, - 165 => 1, - 166 => 1, - 167 => 1, - 172 => 1, - 173 => 1, - 176 => 1, - 177 => 1, - 181 => 1, - 185 => 1, - 188 => 1, - 192 => 1, - 195 => 1, - 200 => 1, + 168 => 1, + 169 => 1, + 170 => 1, + 175 => 1, + 180 => 1, 201 => 1, - 203 => 2, - 207 => 1, - 212 => 1, - 213 => 1, - 214 => 1, + 202 => 1, + 203 => 1, + 204 => 1, 219 => 1, 220 => 1, - 221 => 1, - 226 => 1, - 227 => 1, - 232 => 1, - 245 => 1, - 246 => 1, - 247 => 1, - 252 => 1, - 254 => 1, - 255 => 1, - 256 => 1, - 257 => 1, - 271 => 1, - 272 => 1, - 273 => 1, - 282 => 1, - 296 => 1, - 301 => 1, - 312 => 2, + 229 => 1, + 243 => 1, + 248 => 1, + 259 => 2, ]; } diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc b/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc index eaf4d31d..a72e2c5d 100644 --- a/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc @@ -7,91 +7,6 @@ use MyNamespace\FunctionCommentReturnParent as ParentClass; abstract class FunctionCommentReturn extends ParentClass { - /** - * @return FunctionCommentReturn - */ - abstract public function tagReturnClassNameUseSelfInstead(); - - /** - * @return FunctionCommentReturn[] - */ - abstract public function tagReturnArrayOfClassNamesUseArrayOfSelfInstead(); - - /** - * @return \MyNamespace\Test\Functions\FunctionCommentReturn - */ - abstract public function tagReturnFCQNClassNameUseSelfInstead(); - - /** - * @return \MyNamespace\Test\Functions\FunctionCommentReturn[] - */ - abstract public function tagReturnArrayOfFCQNClassNamesUseArrayOfSelfInstead(); - - /** - * @return ParentClass - */ - abstract public function tagReturnParentClassNameUseParentInstead(); - - /** - * @return ParentClass[] - */ - abstract public function tagReturnArrayOfParentClassNamesUseArrayOfParentInstead(); - - /** - * @return \MyNamespace\FunctionCommentReturnParent - */ - abstract public function tagReturnFCQNParentClassNameUseParentInstead(); - - /** - * @return \MyNamespace\FunctionCommentReturnParent[] - */ - abstract public function tagReturnArrayOfFCQNParentClassNamesUseArrayOfParentInstead(); - - /** - * @return INT|String - */ - abstract public function invalidTypeCaseReturnTag(); - - /** - * @return Boolean|integer - */ - abstract public function invalidReturnTagTypes(); - - /** - * @return true|bool - */ - abstract public function tagBoolAndTrue(); - - /** - * @return false|bool - */ - abstract public function tagBoolAndFalse(); - - /** - * @return false|true - */ - abstract public function tagTrueAndFalse(); - - /** - * @return bool|bool|int - */ - abstract public function duplicatedReturnTypesInTag(); - - /** - * @return string|int|bool|null - */ - abstract public function invalidOrderOfTypesInTag1(); - - /** - * @return DateTime|true|string - */ - abstract public function invalidOrderOfTypesInTag2(); - - /** - * @return DateTime|ArrayObject|\ArrayAccess - */ - abstract public function invalidOrderOfTypesInTag3(); - abstract public function classNameReturnTypeShouldBeSelfInstead() : FunctionCommentReturn; abstract public function nullableClassNameReturnTypeShouldBeSelfInstead() : ?FunctionCommentReturn; @@ -114,25 +29,10 @@ abstract class FunctionCommentReturn extends ParentClass abstract public function returnTypeInvalidPrimitiveTypeCase() : Int; - /** - * @return String - */ - abstract public function returnTagInvalidPrimitiveTypeCase(); - abstract public function returnTypeInvalidComplexTypeCase() : dt; - /** - * @return dt - */ - abstract public function returnTagInvalidComplexTypeCase(); - abstract public function returnTypeCanUseAliasInsteadOfFCQN() : \DateTime; - /** - * @return \DateTime - */ - abstract public function returnTagCanUseAliasInsteadOfFCQN(); - /** * @return \ArrayAccess */ @@ -397,7 +297,4 @@ abstract class FunctionCommentReturn extends ParentClass * @return int|string */ abstract public function returnTypePrimitiveDoesNotMatchWithTag2() : string; - - } - diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc.fixed b/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc.fixed new file mode 100644 index 00000000..ad7ed322 --- /dev/null +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc.fixed @@ -0,0 +1,300 @@ +method($a) && $a[0]; + } + + /** + * @return array|\DateTime[] + */ + public function returnBoolOnlyHasNonBooleanType4() + { + return ! ['array']; + } + + /** + * @return int + */ + public function returnBoolOnlyHasNonBooleanType5($a) + { + if ($a) { + return true; + } + + return false; + } + + /** + * @return int|string + */ + public function returnPossiblyNotBoolAndDoesNotHaveBoolType($a) + { + return ! $a ? true : null; + } + + /** + * @return bool + */ + public function returnBoolAndHasBooleanType1($a) + { + return ! $a; + } + + /** + * @return boolean + */ + public function returnBoolAndHasBooleanType2($a) + { + return (bool) $a; + } + + public function returnBoolAndHasBooleanReturnType1($a) : bool + { + return ! $a; + } + + public function returnBoolAndHasBooleanReturnType2($a) : ?bool + { + return (bool) $a; + } + + public function returnBoolAndHasBooleanReturnType3($a) : bool + { + if ($a) { + return true; + } + + return false; + } + + public function returnBooleanAndHasNotBooleanReturnType($a) : int + { + if ($a) { + return true; + } + + return 1; + } + + /** + * @return false + */ + public function returnTrueOnlyHasNotTrueValue() + { + return true; + } + + /** + * @return true + */ + public function returnFalseOnlyHasNotFalseValue() + { + return false; + } + + /** + * @return string + */ + public function returnIntAndHasNoIntType1($a) + { + if ($a) { + return 2 * $a; + } + + return 0; + } + + /** + * @return float + */ + public function returnIntAndHasNoIntType2($a) + { + if (! is_float($a)) { + return 1; + } + + return $a; + } + + public function returnIntAndHasNoReturnTypeInt1() : string + { + return 1; + } + + public function returnIntAndHasNoReturnTypeInt2() : float + { + return 1; + } + + public function returnIntAndHasIntReturnType1() : int + { + return 1; + } + + public function returnIntAndHasIntReturnType2() : ?int + { + return 0; + } + + public function returnPossiblyNotIntAndHasIntReturnType($a) : ?int + { + return 5 * $a; + } + + /** + * @return float + */ + public function returnPossiblyNotIntAndDoesNotHaveIntType($a) + { + return 5 * $a; + } + + /** + * @return float + */ + public function returnNullButDoesNotHaveNullType($a) + { + if ($a) { + return $a; + } + + return null; + } + + public function returnNullButReturnTypeIsNotNullable($a) : int + { + if ($a) { + return $a; + } + + return null; + } + + /** + * @return string + */ + public function returnFloatAndHasNoFloatType1($a) + { + if ($a) { + return 2 * $a; + } + + return 0.0; + } + + /** + * @return int + */ + public function returnFloatAndHasNoFloatType2($a) + { + if (! is_int($a)) { + return 1.0; + } + + return $a; + } + + public function returnFloatAndHasNoReturnTypeFloat1() : string + { + return 1.0; + } + + public function returnFloatAndHasNoReturnTypeFloat2() : int + { + return 1.0; + } + + public function returnFloatAndHasFloatReturnType1() : float + { + return 1.0; + } + + public function returnFloatAndHasFloatReturnType2() : ?float + { + return 0.0; + } + + public function returnFloatExpressionAndDoesNotHaveFloatReturnType($a) : ?int + { + return 5.0 * $a; + } + + /** + * @return int + */ + public function returnFloatExpressionAndDoesNotHaveFloatType($a) + { + return 5.0 * $a; + } + + /** + * @return object + */ + public function returnNewInstanceFromVariable($a) + { + return new $a; + } + + /** + * @return OtherClass + */ + public function returnNewInstance() + { + return new MyClass; + } + + /** + * @return MyInterface2 + */ + public function returnTwoDifferentInstances($a) : MyNamespace\MyInterface1 + { + if ($a) { + return new MyNamespace\ClassA(); + } + + return new MyNamespace\ClassX(); + } + + /** + * @return $this + */ + public function returnThisOnlyAndHasSelfInTag() + { + return $this; + } + + /** + * @return $this + */ + public function returnThisOnlyAndHasClassNameInTag() + { + return $this; + } + + /** + * @return $this + */ + public function returnThisOnlyAndHasFCQNClassNameInTag() + { + return $this; + } +} diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.3.inc b/test/Sniffs/Functions/ReturnTypeUnitTest.3.inc index 6c694769..5eadd98e 100644 --- a/test/Sniffs/Functions/ReturnTypeUnitTest.3.inc +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.3.inc @@ -7,7 +7,7 @@ class FunctionCommentReturn /** * @return mixed */ - public function test1($x) + public function test($x) : \Generator { return $x; } @@ -15,47 +15,7 @@ class FunctionCommentReturn /** * @return mixed[] */ - public function test2($x) - { - return $x; - } - - /** - * @return mixed|mixed[] - */ - public function test3($x) - { - return $x; - } - - /** - * @return false|mixed - */ - public function test4($x) - { - return $x; - } - - /** - * @return bool|mixed - */ - public function test5($x) - { - return $x; - } - - /** - * @return mixed - */ - public function test6($x) : \Generator - { - return $x; - } - - /** - * @return mixed[] - */ - public function test7($x) : \Generator + public function test($x) : \Generator { return $x; } @@ -63,7 +23,7 @@ class FunctionCommentReturn /** * @return mixed */ - public function test8($x) : \Traversable + public function test($x) : \Traversable { return $x; } @@ -71,7 +31,7 @@ class FunctionCommentReturn /** * @return mixed[] */ - public function test9($x) : \Traversable + public function test($x) : \Traversable { return $x; } @@ -79,7 +39,7 @@ class FunctionCommentReturn /** * @return mixed */ - public function test10($x) : iterable + public function test($x) : iterable { return $x; } @@ -87,7 +47,7 @@ class FunctionCommentReturn /** * @return mixed[] */ - public function test11($x) : iterable + public function test($x) : iterable { return $x; } @@ -95,7 +55,7 @@ class FunctionCommentReturn /** * @return mixed */ - public function test12($x) : array + public function test($x) : array { return $x; } @@ -103,7 +63,7 @@ class FunctionCommentReturn /** * @return mixed[] */ - public function test13($x) : array + public function test($x) : array { return $x; } @@ -111,7 +71,7 @@ class FunctionCommentReturn /** * @return int */ - public function test14($x) : \Generator + public function test($x) : \Generator { return $x; } @@ -119,7 +79,7 @@ class FunctionCommentReturn /** * @return int[] */ - public function test15($x) : \Generator + public function test($x) : \Generator { return $x; } @@ -127,7 +87,7 @@ class FunctionCommentReturn /** * @return MyObj */ - public function test16($x) : \Generator + public function test($x) : \Generator { return $x; } @@ -135,7 +95,7 @@ class FunctionCommentReturn /** * @return int */ - public function test17($x) : \Traversable + public function test($x) : \Traversable { return $x; } @@ -143,7 +103,7 @@ class FunctionCommentReturn /** * @return int[] */ - public function test18($x) : \Traversable + public function test($x) : \Traversable { return $x; } @@ -151,7 +111,7 @@ class FunctionCommentReturn /** * @return MyObj */ - public function test19($x) : \Traversable + public function test($x) : \Traversable { return $x; } @@ -159,7 +119,7 @@ class FunctionCommentReturn /** * @return int */ - public function test20($x) : iterable + public function test($x) : iterable { return $x; } @@ -167,7 +127,7 @@ class FunctionCommentReturn /** * @return int[] */ - public function test21($x) : iterable + public function test($x) : iterable { return $x; } @@ -175,7 +135,7 @@ class FunctionCommentReturn /** * @return MyObj */ - public function test22($x) : iterable + public function test($x) : iterable { return $x; } @@ -183,7 +143,7 @@ class FunctionCommentReturn /** * @return int */ - public function test23($x) : array + public function test($x) : array { return $x; } @@ -191,7 +151,7 @@ class FunctionCommentReturn /** * @return int[] */ - public function test24($x) : array + public function test($x) : array { return $x; } @@ -199,7 +159,7 @@ class FunctionCommentReturn /** * @return MyObj */ - public function test25($x) : array + public function test($x) : array { return $x; } @@ -207,7 +167,7 @@ class FunctionCommentReturn /** * @return null|\Generator */ - public function test26($x) : ?\Generator + public function test($x) : ?\Generator { return $x; } @@ -218,7 +178,7 @@ class FunctionCommentReturn * @var string $label The display name for this element * } */ - public function test27() : array + public function test() : array { return []; } diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.inc b/test/Sniffs/Functions/ReturnTypeUnitTest.inc index 79439032..e2bb78cf 100644 --- a/test/Sniffs/Functions/ReturnTypeUnitTest.inc +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.inc @@ -22,11 +22,6 @@ abstract class FunctionCommentReturn abstract public function voidAbstractMethodNoReturnTag(); - /** - * @return - */ - abstract public function noTypeInReturnTag(); - /** * @return int * @return string @@ -171,66 +166,6 @@ abstract class FunctionCommentReturn return 1; } - /** - * @return void Description is not allowed. - */ - public function voidWithDescription() {} - - /** - * @return void - */ - public function redundantReturnVoidTag() {} - - /** - * @return int,string - */ - abstract public function invalidTypeNotation(); - - /** - * @return array() - */ - abstract public function invalidTypeNotationArray(); - - /** - * @return array[string] - */ - abstract public function invalidTypeNotationArrayKeys(); - - /** - * @return $This - */ - abstract public function returnThisInvalidCase1(); - - /** - * @return null|$THIS - */ - abstract public function returnThisInvalidCase2(); - - /** - * @return null - */ - abstract public function returnOnlyNull(); - - /** - * @return null[][] - */ - abstract public function returnOnlyNullArray(); - - /** - * @return void|int - */ - abstract public function voidMixedWithOtherTypes(); - - /** - * @return mixed - */ - abstract public function mixedTypeIsAllowed(); - - /** - * @return mixed[][] - */ - abstract public function mixedArrayTypeIsAllowed(); - abstract public function returnTypeArrayDoesNotNeedSpecification() : array; abstract public function returnTypeNullableArrayDoesNotNeedSpecification() : ?array; @@ -256,52 +191,7 @@ abstract class FunctionCommentReturn abstract public function returnTypeNullableIterableDoesNotNeedSpecification() : ?iterable; /** - * @return array - */ - abstract public function tagReturnTypeArrayNeedsSpecification(); - - /** - * @return array[] - */ - abstract public function tarReturnTypeArrayOfArraysNeedsSpecification(); - - /** - * @return \Traversable - */ - abstract public function tagReturnTypeTraversableNeedsSpecification(); - - /** - * @return Traversable[] - */ - abstract public function tagReturnTypeArrayOfTraversableNeedsSpecification(); - - /** - * @return \Generator[] - */ - abstract public function tagReturnTypeGeneratorNeedsSpecification(); - - /** - * @return Generator - */ - abstract public function tagReturnTypeArrayOfGeneratorNeedsSpecification(); - - /** - * @return iterable - */ - abstract public function tagReturnTypeIterableNeedsSpecification(); - - /** - * @return iterable[] - */ - abstract public function tagReturnTypeArrayOfIterableNeedsSpecification(); - - /** - * @return Array[]|iterable|array|ITerable[][]|Traversable|\traversable[] - */ - abstract public function allTagTypesNeedSpecification(); - - /** - * @return Null|TRUE + * @return bool|int We don't know the exact type here. */ public function returnNullOrTrueWrongCaseInTag() { @@ -309,7 +199,7 @@ abstract class FunctionCommentReturn } /** - * @return null|False + * @return string We don't know the exact type here. */ public function returnNullOrFalseWrongCaseInTag() { @@ -328,4 +218,24 @@ abstract class FunctionCommentReturn return []; } + + /** + * @return + */ + abstract public function missingType(); + + /** + * @return int,string + */ + abstract public function invalidType(); + + /** + * @return null + */ + abstract public function returnNull(); + + /** + * @return null[] + */ + abstract public function returnNullArray(); } diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.php b/test/Sniffs/Functions/ReturnTypeUnitTest.php index 3998c6a2..858b8a7a 100644 --- a/test/Sniffs/Functions/ReturnTypeUnitTest.php +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.php @@ -17,85 +17,62 @@ public function getErrorList($testFile = '') switch ($testFile) { case 'ReturnTypeUnitTest.1.inc': return [ - 11 => 1, - 16 => 1, - 21 => 1, - 26 => 1, - 31 => 1, - 36 => 1, - 41 => 1, - 46 => 1, - 51 => 2, - 56 => 2, - 61 => 1, - 66 => 1, - 71 => 1, - 76 => 1, - 81 => 1, - 86 => 1, - 91 => 1, - 95 => 1, + 10 => 1, + 12 => 1, + 15 => 1, + 18 => 1, + 20 => 1, + 22 => 1, + 25 => 1, + 28 => 1, + 30 => 1, + 32 => 1, + 34 => 1, + 37 => 1, + 42 => 1, + 47 => 1, + 52 => 1, + 57 => 1, + 62 => 1, + 67 => 1, + 77 => 1, + 82 => 1, + 92 => 1, 97 => 1, - 100 => 1, - 103 => 1, - 105 => 1, 107 => 1, - 110 => 1, - 113 => 1, - 115 => 1, - 118 => 1, + 112 => 1, + 117 => 1, // in theory we can return here another class of the same parent type... 122 => 1, - 125 => 1, - 129 => 1, - 132 => 1, + 127 => 1, + // 132 => 1, // There is no error, because return type is invalid + 134 => 1, 137 => 1, 142 => 1, 147 => 1, 152 => 1, - 157 => 1, - 162 => 1, - 167 => 2, - 177 => 1, - 182 => 2, - 192 => 1, - 197 => 2, + 167 => 1, + 182 => 1, + 197 => 1, + 202 => 1, 207 => 1, - 212 => 2, - 217 => 1, // in theory we can return here another class of the same parent type... + // 212 => 1, // There is no error, because return type is invalid + 214 => 1, + 217 => 1, 222 => 1, - 227 => 2, - // 232 => 1, // There is no error, because return type is invalid - 234 => 1, + 227 => 1, 237 => 1, 242 => 1, - 247 => 2, 252 => 1, + 257 => 1, 262 => 1, 267 => 1, - 277 => 1, + 272 => 1, + // 277 => 1, // There is no error, because return type is invalid + 279 => 1, 282 => 1, + 287 => 2, 292 => 1, 297 => 1, - 302 => 1, - 307 => 2, - // 312 => 1, // There is no error, because return type is invalid - 314 => 1, - 317 => 1, - 322 => 1, - 327 => 2, - 337 => 1, - 342 => 2, - 352 => 1, - 357 => 2, - 362 => 1, - 367 => 1, - 372 => 2, - // 377 => 1, // There is no error, because return type is invalid - 379 => 1, - 382 => 1, - 387 => 2, - 392 => 1, - 397 => 1, ]; case 'ReturnTypeUnitTest.2.inc': return [ @@ -135,7 +112,6 @@ public function getErrorList($testFile = '') 84 => 1, 96 => 1, 104 => 1, - 108 => 1, 112 => 1, 116 => 1, 124 => 1, @@ -149,7 +125,6 @@ public function getErrorList($testFile = '') 204 => 1, 213 => 1, 216 => 1, - 236 => 1, 265 => 1, 272 => 1, 276 => 1, @@ -169,23 +144,20 @@ public function getErrorList($testFile = '') 419 => 1, 431 => 1, 451 => 1, - 459 => 2, - 467 => 2, + 459 => 1, + 467 => 1, ]; case 'ReturnTypeUnitTest.3.inc': return [ - 24 => 2, - 32 => 1, + 8 => 1, + 24 => 1, 40 => 1, - 48 => 1, - 64 => 1, - 80 => 1, + 56 => 1, + 72 => 1, 96 => 1, - 112 => 1, - 136 => 1, + 120 => 1, + 144 => 1, 160 => 1, - 184 => 1, - 200 => 1, ]; } @@ -196,31 +168,17 @@ public function getErrorList($testFile = '') 16 => 1, 18 => 1, 20 => 1, - 26 => 1, - 32 => 1, + 27 => 1, + 36 => 1, 41 => 1, 46 => 1, - 51 => 1, - 100 => 1, - 104 => 1, - 113 => 1, - 124 => 1, - 133 => 1, - 142 => 1, - 155 => 1, - 175 => 1, - 180 => 1, - 185 => 1, - 190 => 1, - 195 => 1, - 200 => 1, - 205 => 1, - 210 => 1, - 215 => 1, - 220 => 1, - 299 => 2, - 304 => 2, - 312 => 1, + 95 => 1, + 99 => 1, + 108 => 1, + 119 => 1, + 128 => 1, + 137 => 1, + 150 => 1, ]; } From 9958a1f66c760c98aca234c4637e5c610a8e2032 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Feb 2018 20:48:30 +0000 Subject: [PATCH 184/225] Updated VariableComment sniff to check class properties comments --- .../Commenting/VariableCommentSniff.php | 139 +++++++++++------- .../PHP/ImportInternalConstantSniff.php | 4 +- .../PHP/ImportInternalFunctionSniff.php | 4 +- .../Sniffs/PHP/TypeCastingSniff.php | 3 + .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 21 +++ src/ZendCodingStandard/ruleset.xml | 7 - .../Commenting/VariableCommentUnitTest.inc | 56 +++++++ .../Commenting/VariableCommentUnitTest.php | 37 +++++ 8 files changed, 210 insertions(+), 61 deletions(-) create mode 100644 test/Sniffs/Commenting/VariableCommentUnitTest.inc create mode 100644 test/Sniffs/Commenting/VariableCommentUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php index a3368c3f..237ea8e3 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/VariableCommentSniff.php @@ -1,10 +1,4 @@ addError('Missing member variable doc comment', $stackPtr, 'Missing'); + $error = 'Missing member variable doc comment'; + $phpcsFile->addError($error, $stackPtr, 'Missing'); return; } if ($tokens[$commentEnd]['code'] === T_COMMENT) { if ($tokens[$commentEnd]['line'] === $tokens[$stackPtr]['line'] - 1) { $error = 'You must use "/**" style comments for a member variable comment'; - $phpcsFile->addError($error, $stackPtr, 'WrongStyle'); + $phpcsFile->addError($error, $commentEnd, 'WrongStyle'); + } else { + $error = 'Missing member variable doc comment'; + $phpcsFile->addError($error, $stackPtr, 'Missing'); } return; @@ -62,63 +75,89 @@ protected function processMemberVar(File $phpcsFile, $stackPtr) : void $commentStart = $tokens[$commentEnd]['comment_opener']; $foundVar = null; - foreach ($tokens[$commentStart]['comment_tags'] as $tag) { - if ($tokens[$tag]['content'] === '@var') { + + $tags = $tokens[$commentStart]['comment_tags']; + while ($tag = current($tags)) { + $key = key($tags); + if (isset($tags[$key + 1])) { + $lastFrom = $tags[$key + 1]; + } else { + $lastFrom = $tokens[$commentStart]['comment_closer']; + } + + $last = $phpcsFile->findPrevious( + [T_DOC_COMMENT_STAR, T_DOC_COMMENT_WHITESPACE], + $lastFrom - 1, + null, + true + ); + + if (substr($tokens[$last]['content'], -1) === '{') { + $dep = 1; + $i = $last; + $max = $tokens[$commentStart]['comment_closer']; + while ($dep > 0 && $i < $max) { + $i = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $i + 1, $max); + + if (! $i) { + break; + } + + if ($tokens[$i]['content'][0] === '}') { + --$dep; + } + + if (substr($tokens[$i]['content'], -1) === '{') { + ++$dep; + } + } + + if ($dep > 0) { + $error = 'Tag contains nested description, but cannot find the closing bracket'; + $phpcsFile->addError($error, $last, 'NotClosed'); + return; + } + + while (isset($tags[$key + 1]) && $tags[$key + 1] < $i) { + $tagName = strtolower($tokens[$tags[$key + 1]]['content']); + if (! array_filter($this->nestedTags, function ($v) use ($tagName) { + return strtolower($v) === $tagName; + })) { + $error = 'Tag %s cannot be nested.'; + $data = [ + $tokens[$tags[$key + 1]]['content'], + ]; + $phpcsFile->addError($error, $tags[$key + 1], 'NestedTag', $data); + return; + } + + $nestedTags[] = $tags[$key + 1]; + + next($tags); + ++$key; + } + } + + if (strtolower($tokens[$tag]['content']) === '@var') { if ($foundVar !== null) { $error = 'Only one @var tag is allowed in a member variable comment'; $phpcsFile->addError($error, $tag, 'DuplicateVar'); } else { $foundVar = $tag; } - } elseif ($tokens[$tag]['content'] === '@see') { - // Make sure the tag isn't empty. - $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); - if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { - $error = 'Content missing for @see tag in member variable comment'; - $phpcsFile->addError($error, $tag, 'EmptySees'); - } } else { $error = '%s tag is not allowed in member variable comment'; $data = [$tokens[$tag]['content']]; - $phpcsFile->addWarning($error, $tag, 'TagNotAllowed', $data); + $phpcsFile->addError($error, $tag, 'TagNotAllowed', $data); } + + next($tags); } // The @var tag is the only one we require. if ($foundVar === null) { $error = 'Missing @var tag in member variable comment'; $phpcsFile->addError($error, $commentEnd, 'MissingVar'); - return; - } - - $firstTag = $tokens[$commentStart]['comment_tags'][0]; - if ($foundVar !== null && $tokens[$firstTag]['content'] !== '@var') { - $error = 'The @var tag must be the first tag in a member variable comment'; - $phpcsFile->addError($error, $foundVar, 'VarOrder'); - } - - // Make sure the tag isn't empty and has the correct padding. - $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $foundVar, $commentEnd); - if ($string === false || $tokens[$string]['line'] !== $tokens[$foundVar]['line']) { - $error = 'Content missing for @var tag in member variable comment'; - $phpcsFile->addError($error, $foundVar, 'EmptyVar'); - return; - } - - $varType = $tokens[$foundVar + 2]['content']; - // changed to use bool and int instead of boolean and integer accordingly - $suggestedType = CodingStandard::suggestType($varType); - if ($varType !== $suggestedType) { - $error = 'Expected "%s" but found "%s" for @var tag in member variable comment'; - $data = [ - $suggestedType, - $varType, - ]; - $fix = $phpcsFile->addFixableError($error, $foundVar + 2, 'IncorrectVarType', $data); - - if ($fix) { - $phpcsFile->fixer->replaceToken($foundVar + 2, $suggestedType); - } } } diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php index f22fe2b9..1af5cae6 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php @@ -31,7 +31,7 @@ class ImportInternalConstantSniff implements Sniff use Namespaces; /** - * @var array Hash map of all php built in constant names. + * @var array Hash map of all php built in constant names. */ private $builtInConstants; @@ -46,7 +46,7 @@ class ImportInternalConstantSniff implements Sniff private $currentNamespace; /** - * @var array Array of imported constant in current namespace. + * @var array Array of imported constant in current namespace. */ private $importedConstants; diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php index ef5f84fa..d996578c 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php @@ -30,7 +30,7 @@ class ImportInternalFunctionSniff implements Sniff use Namespaces; /** - * @var array Hash map of all php built in function names. + * @var array Hash map of all php built in function names. */ private $builtInFunctions; @@ -45,7 +45,7 @@ class ImportInternalFunctionSniff implements Sniff private $currentNamespace; /** - * @var array Array of imported function in current namespace. + * @var array Array of imported function in current namespace. */ private $importedFunctions; diff --git a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php index 69bf7b5d..e44d0712 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -17,6 +17,9 @@ class TypeCastingSniff implements Sniff { + /** + * @var array + */ private $castMap = [ '(boolean)' => '(bool)', '(integer)' => '(int)', diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index e3bfbb41..e48c9601 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -65,10 +65,19 @@ class ScopeIndentSniff implements Sniff { + /** + * @var int + */ public $indent = 4; + /** + * @var bool + */ public $alignObjectOperators = true; + /** + * @var int[] + */ private $controlStructures = [ T_IF => T_IF, T_ELSEIF => T_ELSEIF, @@ -79,6 +88,9 @@ class ScopeIndentSniff implements Sniff T_CATCH => T_CATCH, ]; + /** + * @var int[] + */ private $endOfStatement = [ T_SEMICOLON, T_CLOSE_CURLY_BRACKET, @@ -91,6 +103,9 @@ class ScopeIndentSniff implements Sniff T_OPEN_SHORT_ARRAY, ]; + /** + * @var int[] + */ private $caseEndToken = [ T_BREAK, T_CONTINUE, @@ -99,8 +114,14 @@ class ScopeIndentSniff implements Sniff T_EXIT, ]; + /** + * @var int[] + */ private $breakToken; + /** + * @var int[] + */ private $functionToken; public function __construct() diff --git a/src/ZendCodingStandard/ruleset.xml b/src/ZendCodingStandard/ruleset.xml index 756858aa..09c05d46 100755 --- a/src/ZendCodingStandard/ruleset.xml +++ b/src/ZendCodingStandard/ruleset.xml @@ -68,11 +68,4 @@ - - - - - - - diff --git a/test/Sniffs/Commenting/VariableCommentUnitTest.inc b/test/Sniffs/Commenting/VariableCommentUnitTest.inc new file mode 100644 index 00000000..3732309c --- /dev/null +++ b/test/Sniffs/Commenting/VariableCommentUnitTest.inc @@ -0,0 +1,56 @@ + 1, + 9 => 1, + 11 => 1, + 29 => 1, + 34 => 1, + 43 => 1, + 51 => 2, + 54 => 2, + ]; + } + + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') + { + return []; + } +} From b452bfe6ae5b46b8fe0ca474fb775e0da10df010 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Feb 2018 21:36:28 +0000 Subject: [PATCH 185/225] Tag with content check moved to DocComment sniff The check should be done in all PHPDocs not only function doc comments. --- .../Sniffs/Commenting/DocCommentSniff.php | 20 +++++++++++++++++-- .../Commenting/FunctionCommentSniff.php | 19 ------------------ test/Sniffs/Commenting/DocCommentUnitTest.inc | 5 +++++ .../Commenting/DocCommentUnitTest.inc.fixed | 5 +++++ test/Sniffs/Commenting/DocCommentUnitTest.php | 1 + .../Commenting/FunctionCommentUnitTest.inc | 5 ----- .../FunctionCommentUnitTest.inc.fixed | 5 ----- .../Commenting/FunctionCommentUnitTest.php | 19 +++++++++--------- 8 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index d73cffb0..8d686ac1 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -51,6 +51,13 @@ class DocCommentSniff implements Sniff '@throws', ]; + /** + * @var string[] + */ + public $tagsWithContent = [ + '@see', + ]; + /** * @return int[] */ @@ -75,7 +82,7 @@ public function process(File $phpcsFile, $stackPtr) $this->checkBeforeOpen($phpcsFile, $commentStart); $this->checkAfterClose($phpcsFile, $commentStart, $commentEnd); $this->checkCommentIndents($phpcsFile, $commentStart, $commentEnd); - $this->checkTagsSpaces($phpcsFile, $commentStart); + $this->checkTagsSpaces($phpcsFile, $commentStart, $commentEnd); $this->checkInheritDoc($phpcsFile, $commentStart, $commentEnd); // Doc block comment in one line. @@ -730,7 +737,7 @@ private function checkBlankLineBeforeTags(File $phpcsFile, int $commentStart) : } } - private function checkTagsSpaces(File $phpcsFile, int $commentStart) : void + private function checkTagsSpaces(File $phpcsFile, int $commentStart, int $commentEnd) : void { $tokens = $phpcsFile->getTokens(); @@ -753,6 +760,15 @@ private function checkTagsSpaces(File $phpcsFile, int $commentStart) : void continue; } + if (in_array($tokens[$tag]['content'], $this->tagsWithContent, true)) { + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if (! $string || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for %s tag in PHPDoc comment'; + $data = $tokens[$tag]['content']; + $phpcsFile->addError($error, $tag, 'EmptyTagContent', $data); + } + } + // Continue if next token contains new line. if (strpos($tokens[$tag + 1]['content'], $phpcsFile->eolChar) !== false) { continue; diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index cc564bc0..5f2cf23b 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -87,29 +87,10 @@ public function process(File $phpcsFile, $stackPtr) $commentStart = $tokens[$commentEnd]['comment_opener']; - $this->processSee($phpcsFile, $commentStart, $commentEnd); $this->processTagOrder($phpcsFile, $commentStart); } } - private function processSee(File $phpcsFile, int $commentStart, int $commentEnd) : void - { - $tokens = $phpcsFile->getTokens(); - - foreach ($tokens[$commentStart]['comment_tags'] as $tag) { - if (strtolower($tokens[$tag]['content']) !== '@see') { - continue; - } - - // Make sure the tag isn't empty. - $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); - if (! $string || $tokens[$string]['line'] !== $tokens[$tag]['line']) { - $error = 'Content missing for @see tag in function comment'; - $phpcsFile->addError($error, $tag, 'EmptySees'); - } - } - } - private function processTagOrder(File $phpcsFile, int $commentStart) : void { $tokens = $phpcsFile->getTokens(); diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc b/test/Sniffs/Commenting/DocCommentUnitTest.inc index 1065f04c..f9678fa4 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc @@ -241,4 +241,9 @@ class Foo * @inheritdoc */ private function inheritDocTag2() {} + + /** + * @see + */ + private function emptySeeContent() {} } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed index a056d081..94dee74b 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed @@ -243,4 +243,9 @@ $c = 'xyz'; * @inheritdoc */ private function inheritDocTag2() {} + + /** + * @see + */ + private function emptySeeContent() {} } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.php b/test/Sniffs/Commenting/DocCommentUnitTest.php index 623e9289..46583dac 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.php +++ b/test/Sniffs/Commenting/DocCommentUnitTest.php @@ -168,6 +168,7 @@ public function getErrorList($testFile = '') 229 => 1, 236 => 1, 241 => 1, + 246 => 1, ]; } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc index d4a688d0..d7437dbd 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc @@ -25,11 +25,6 @@ class Foo */ private function tagsOrder($a, $b, $c, $d) {} - /** - * @see - */ - private function seeMissingContent() {} - /** * @dataProvider something * @param int $a diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed index d6124f2c..13a0b3b1 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed @@ -26,11 +26,6 @@ class Foo */ private function tagsOrder($a, $b, $c, $d) {} - /** - * @see - */ - private function seeMissingContent() {} - /** * @dataProvider something * diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.php b/test/Sniffs/Commenting/FunctionCommentUnitTest.php index d0415034..44f5ecd2 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.php +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.php @@ -18,16 +18,15 @@ public function getErrorList($testFile = '') 7 => 1, 11 => 1, 17 => 1, - 29 => 1, - 35 => 1, - 36 => 1, - 39 => 1, - 42 => 1, - 49 => 1, - 57 => 1, - 72 => 1, - 79 => 1, - 85 => 1, + 30 => 1, + 31 => 1, + 34 => 1, + 37 => 1, + 44 => 1, + 52 => 1, + 67 => 1, + 74 => 1, + 80 => 1, ]; } From 2a2e49bcbc4ccf84d30476b18c75b15c2b8b89b7 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Feb 2018 21:46:21 +0000 Subject: [PATCH 186/225] Multiline function comments --- .../Sniffs/Commenting/FunctionCommentSniff.php | 9 +++++++++ test/Sniffs/Commenting/FunctionCommentUnitTest.inc | 3 +++ test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed | 4 ++++ test/Sniffs/Commenting/FunctionCommentUnitTest.php | 1 + 4 files changed, 17 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index 5f2cf23b..fa03dac7 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -88,6 +88,15 @@ public function process(File $phpcsFile, $stackPtr) $commentStart = $tokens[$commentEnd]['comment_opener']; $this->processTagOrder($phpcsFile, $commentStart); + + if ($tokens[$commentStart]['line'] === $tokens[$commentEnd]['line']) { + $error = 'Function comment must be multiline comment'; + $fix = $phpcsFile->addFixableError($error, $commentStart, 'SingleLine'); + + if ($fix) { + $phpcsFile->fixer->addContent($commentStart, $phpcsFile->eolChar . ' *'); + } + } } } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc index d7437dbd..63c7fcc2 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc @@ -92,4 +92,7 @@ class Foo * } */ private function twoLevelNesting(array $a) {} + + /** @return void */ + private function inlineComment() {} } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed index 13a0b3b1..65ffacfc 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.inc.fixed @@ -87,4 +87,8 @@ class Foo * } */ private function twoLevelNesting(array $a) {} + + /** + * @return void */ + private function inlineComment() {} } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.php b/test/Sniffs/Commenting/FunctionCommentUnitTest.php index 44f5ecd2..32de740f 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.php +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.php @@ -27,6 +27,7 @@ public function getErrorList($testFile = '') 67 => 1, 74 => 1, 80 => 1, + 96 => 1, ]; } From 30fd9b4f5db12633ea5c33459feceea457efcdf1 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Feb 2018 22:05:57 +0000 Subject: [PATCH 187/225] Added ConstVisibility sniff --- .../Sniffs/Classes/ConstVisibilitySniff.php | 47 +++++++++++++++++++ .../Classes/ConstVisibilityUnitTest.inc | 30 ++++++++++++ .../Classes/ConstVisibilityUnitTest.php | 32 +++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/Classes/ConstVisibilitySniff.php create mode 100644 test/Sniffs/Classes/ConstVisibilityUnitTest.inc create mode 100644 test/Sniffs/Classes/ConstVisibilityUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Classes/ConstVisibilitySniff.php b/src/ZendCodingStandard/Sniffs/Classes/ConstVisibilitySniff.php new file mode 100644 index 00000000..13bb1c5d --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Classes/ConstVisibilitySniff.php @@ -0,0 +1,47 @@ +getTokens(); + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); + + if (! in_array($tokens[$prev]['code'], Tokens::$scopeModifiers, true)) { + $error = 'Missing constant visibility'; + $phpcsFile->addError($error, $stackPtr, 'MissingVisibility'); + } + } + + /** + * @param int $stackPtr + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) : void + { + // do not process constant outside the scope + } +} diff --git a/test/Sniffs/Classes/ConstVisibilityUnitTest.inc b/test/Sniffs/Classes/ConstVisibilityUnitTest.inc new file mode 100644 index 00000000..f8bed8f9 --- /dev/null +++ b/test/Sniffs/Classes/ConstVisibilityUnitTest.inc @@ -0,0 +1,30 @@ + 1, + 15 => 1, + 23 => 1, + ]; + } + + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') + { + return []; + } +} From 8dc06338ab24fa8d5cd9c6e728878bcf1de91513 Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Mar 2018 09:18:11 +0000 Subject: [PATCH 188/225] UnnecessaryParentheses sniff fix Do not remove parentheses when there is arythmetic or boolean operator before or after expression. - per @Xerkus --- .../Sniffs/Formatting/UnnecessaryParenthesesSniff.php | 6 ++++++ test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc | 3 +++ .../Formatting/UnnecessaryParenthesesUnitTest.inc.fixed | 3 +++ 3 files changed, 12 insertions(+) diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php index 00c9b9dd..75b16626 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -156,10 +156,16 @@ public function process(File $phpcsFile, $stackPtr) } } + // Skip when operator before the parenthesis if (in_array($tokens[$prev]['code'], Tokens::$operators + Tokens::$booleanOperators, true)) { return; } + // Skip when operator after the parenthesis + if (in_array($tokens[$next]['code'], Tokens::$operators + Tokens::$booleanOperators, true)) { + return; + } + // Check single expression casting if (in_array($tokens[$prev]['code'], Tokens::$castTokens, true)) { $op = $phpcsFile->findNext( diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc index 9351a2b6..44f2d66b 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc @@ -159,5 +159,8 @@ class UnnecessaryParentheses $a = $b ? 0 : ($c ?? 1); new $arr['abc']['def'](); + + $r = $a === ($b + $c) * $d; + $r = $a === $d * ($b + $c); } } diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed index 1f3d7dd7..c2e8c098 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed @@ -159,5 +159,8 @@ class UnnecessaryParentheses $a = $b ? 0 : ($c ?? 1); new $arr['abc']['def'](); + + $r = $a === ($b + $c) * $d; + $r = $a === $d * ($b + $c); } } From c8d20930df232335331ec02a8d10794fa1ea9f7d Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Mar 2018 09:22:01 +0000 Subject: [PATCH 189/225] UnnecessaryParentheses sniff fix Allow unnecessary parentheses in case of comparision to improve readability eg. `return $a === ($b + $c)` - per @Xerkus --- .../Sniffs/Formatting/UnnecessaryParenthesesSniff.php | 3 ++- test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc | 2 ++ .../Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php index 75b16626..7b2db756 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -216,7 +216,8 @@ public function process(File $phpcsFile, $stackPtr) // Check single expression comparision if (in_array($tokens[$prev]['code'], Tokens::$equalityTokens, true)) { $op = $phpcsFile->findNext( - Tokens::$assignmentTokens + Tokens::$arithmeticTokens + + Tokens::$assignmentTokens + Tokens::$booleanOperators + [ T_BITWISE_AND => T_BITWISE_AND, diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc index 44f2d66b..d3099646 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc @@ -162,5 +162,7 @@ class UnnecessaryParentheses $r = $a === ($b + $c) * $d; $r = $a === $d * ($b + $c); + $r = $a === $b + $c; + $r = $a === ($b + $c); } } diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed index c2e8c098..843ddcbb 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.inc.fixed @@ -162,5 +162,7 @@ class UnnecessaryParentheses $r = $a === ($b + $c) * $d; $r = $a === $d * ($b + $c); + $r = $a === $b + $c; + $r = $a === ($b + $c); } } From c8205ee60c6210309c0240b38d18d5c7927763eb Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Mar 2018 10:04:17 +0000 Subject: [PATCH 190/225] Require variable name with `@var` tag for non-class members - per @Xerkus --- .../Sniffs/Commenting/TagWithTypeSniff.php | 25 +++++++++++++------ .../Commenting/TagWithTypeUnitTest.3.inc | 12 +++++++++ .../TagWithTypeUnitTest.3.inc.fixed | 12 +++++++++ .../Sniffs/Commenting/TagWithTypeUnitTest.php | 2 ++ 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php index d237a86a..23d86b23 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php @@ -6,12 +6,14 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; use ZendCodingStandard\Helper\Methods; use function array_filter; use function array_shift; use function array_unique; use function count; +use function end; use function explode; use function implode; use function in_array; @@ -233,19 +235,26 @@ private function processVarTag(File $phpcsFile, int $tagPtr) : bool $i = $phpcsFile->findPrevious([T_DOC_COMMENT_TAG, T_DOC_COMMENT_OPEN_TAG], $i - 1); } + $condition = end($tokens[$tagPtr]['conditions']); + $isMemberVar = isset(Tokens::$ooScopeTokens[$condition]); + $split = preg_split('/\s/', $tokens[$tagPtr + 2]['content'], 3); - if ($nested > 0) { - if (! empty($split[0][0]) && $split[0][0] === '$') { - $error = 'Missing variable type'; - $phpcsFile->addError($error, $tagPtr + 2, 'MissingVarType'); + if ($nested > 0 || ! $isMemberVar) { + if (! isset($split[1])) { + if ($this->isVariable($split[0])) { + $error = 'Missing variable type'; + $phpcsFile->addError($error, $tagPtr + 2, 'MissingVarType'); + } else { + $error = 'Missing variable name in PHPDocs'; + $phpcsFile->addError($error, $tagPtr + 2, 'MissingVarName'); + } return false; } - if (empty($split[1]) || (! empty($split[1][0]) && $split[1][0] !== '$')) { - $error = 'Missing variable name'; - $phpcsFile->addError($error, $tagPtr + 2, 'MissingVarName'); - + if (! $this->isVariable($split[1])) { + $error = empty($split[1]) ? 'Missing variable name in PHPDocs' : 'Invalid variable name'; + $phpcsFile->addError($error, $tagPtr + 2, 'InvalidVarName'); return false; } diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc b/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc index 56a97d53..aece4ed8 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc @@ -284,4 +284,16 @@ class VarTag extends VarTagParent { * } */ public $a; + + public function test() + { + /** @var int */ + foreach (func_get_args() as $a) { + } + + new class () { + /** @var bool $a */ + private $a; + }; + } } diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc.fixed b/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc.fixed index 020bb65b..d70fd95d 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc.fixed +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc.fixed @@ -284,4 +284,16 @@ class VarTag extends VarTagParent { * } */ public $a; + + public function test() + { + /** @var int */ + foreach (func_get_args() as $a) { + } + + new class () { + /** @var bool */ + private $a; + }; + } } diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.php b/test/Sniffs/Commenting/TagWithTypeUnitTest.php index c2445575..71c6e45b 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.php +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.php @@ -171,6 +171,8 @@ public function getErrorList($testFile = '') 272 => 1, 281 => 1, 282 => 1, + 290 => 1, + 295 => 1, ]; } From 285f3976972e4f0f104def4c878f9d96ba72183a Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 5 Mar 2018 10:05:53 +0000 Subject: [PATCH 191/225] Improve error message for missing parameter name in PHPDocs --- src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php index 23d86b23..5e4e9e97 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php @@ -208,7 +208,7 @@ private function processParamTag(File $phpcsFile, int $tagPtr) : bool } if (! $this->isVariable($split[1])) { - $error = 'Invalid parameter name'; + $error = empty($split[1]) ? 'Missing parameter name in PHPDocs' : 'Invalid parameter name'; $phpcsFile->addError($error, $tagPtr + 2, 'InvalidParamName'); return false; } From d43afdb0faaa6e5beba9de1e5daf824567560d19 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 6 Mar 2018 07:31:09 +0000 Subject: [PATCH 192/225] Fixed error message - data providers without Provider suffix - per @Xerkus --- .../Sniffs/Commenting/FunctionDataProviderTagSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionDataProviderTagSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionDataProviderTagSniff.php index 892d33f7..f89f455b 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionDataProviderTagSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionDataProviderTagSniff.php @@ -81,7 +81,7 @@ public function process(File $phpcsFile, $stackPtr) $providerName = $tokens[$tag + 2]['content']; if (preg_match('/Provider$/', $providerName)) { - $error = 'Data provider name should have "Provider" suffix.'; + $error = 'Data provider name should not have "Provider" suffix.'; $phpcsFile->addError($error, $tag, 'DataProviderInvalidName'); } } From ad855881b8aa03559ce02075582c3b519f16bddb Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 7 Mar 2018 12:49:56 +0000 Subject: [PATCH 193/225] Added new sniff SingleSemicolon - per @Xerkus --- .../Sniffs/PHP/SingleSemicolonSniff.php | 40 +++++++++++++++++++ test/Sniffs/PHP/SingleSemicolonUnitTest.inc | 5 +++ .../PHP/SingleSemicolonUnitTest.inc.fixed | 5 +++ test/Sniffs/PHP/SingleSemicolonUnitTest.php | 31 ++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/PHP/SingleSemicolonSniff.php create mode 100644 test/Sniffs/PHP/SingleSemicolonUnitTest.inc create mode 100644 test/Sniffs/PHP/SingleSemicolonUnitTest.inc.fixed create mode 100644 test/Sniffs/PHP/SingleSemicolonUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/PHP/SingleSemicolonSniff.php b/src/ZendCodingStandard/Sniffs/PHP/SingleSemicolonSniff.php new file mode 100644 index 00000000..032d63ea --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/PHP/SingleSemicolonSniff.php @@ -0,0 +1,40 @@ +getTokens(); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); + + if ($next && $tokens[$next]['code'] === T_SEMICOLON) { + $error = 'Redundant semicolon'; + $fix = $phpcsFile->addFixableError($error, $next, 'Semicolon'); + + if ($fix) { + $phpcsFile->fixer->replaceToken($next, ''); + } + } + } +} diff --git a/test/Sniffs/PHP/SingleSemicolonUnitTest.inc b/test/Sniffs/PHP/SingleSemicolonUnitTest.inc new file mode 100644 index 00000000..252e804d --- /dev/null +++ b/test/Sniffs/PHP/SingleSemicolonUnitTest.inc @@ -0,0 +1,5 @@ + 1, + 5 => 3, + ]; + } + + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') + { + return []; + } +} From 605a75250b5069a63b4cde4492593997c0d73b00 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 7 Mar 2018 13:44:21 +0000 Subject: [PATCH 194/225] Better autofixing indents in doc comments tag descriptions - per @Xerkus --- .../Sniffs/Commenting/DocCommentSniff.php | 11 ++++++++++- test/Sniffs/Commenting/DocCommentUnitTest.inc | 14 ++++++++++++++ .../Commenting/DocCommentUnitTest.inc.fixed | 16 +++++++++++++++- test/Sniffs/Commenting/DocCommentUnitTest.php | 7 +++++++ 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php index 8d686ac1..149db3f5 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/DocCommentSniff.php @@ -371,6 +371,7 @@ private function checkSpacesAfterStar(File $phpcsFile, int $commentStart, int $c $tokens = $phpcsFile->getTokens(); $firstTag = $tokens[$commentStart]['comment_tags'][0] ?? null; + $replaces = []; $next = $commentStart; $search = [T_DOC_COMMENT_STAR, T_DOC_COMMENT_CLOSE_TAG]; while ($next = $phpcsFile->findNext($search, $next + 1, $commentEnd + 1)) { @@ -439,6 +440,10 @@ private function checkSpacesAfterStar(File $phpcsFile, int $commentStart, int $c } $spaces = strlen(preg_replace('/^( *).*$/', '\\1', $tokens[$next + 1]['content'])); + if (! isset($replaces[$prev][$spaces])) { + $replaces[$prev][$spaces] = $spaces; + } + if ($tokens[$prev]['code'] === T_DOC_COMMENT_TAG && ($spaces < $expectedSpaces || (($spaces - 1) % $this->indent) !== 0 @@ -457,12 +462,16 @@ private function checkSpacesAfterStar(File $phpcsFile, int $commentStart, int $c ); if ($tokens[$prev2]['line'] === $tokens[$next]['line'] - 1) { - if ($tokens[$prev]['line'] !== $tokens[$next + 1]['line'] - 1) { + if (isset($replaces[$prev][$spaces]) && $replaces[$prev][$spaces] !== $spaces) { + $expectedSpaces = $replaces[$prev][$spaces]; + } elseif ($tokens[$prev]['line'] !== $tokens[$next + 1]['line'] - 1) { $expectedSpaces = 1 + (int) max( round(($spaces - 1) / $this->indent) * $this->indent, $this->indent ); } + $replaces[$prev][$spaces] = $expectedSpaces; + $error = 'Invalid indent before description; expected %d spaces, found %d'; $data = [ $expectedSpaces, diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc b/test/Sniffs/Commenting/DocCommentUnitTest.inc index f9678fa4..cdfb32f8 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc @@ -246,4 +246,18 @@ class Foo * @see */ private function emptySeeContent() {} + + /** + * @triggers Comment here + * and continuation here + * and here + * @triggers Something + * else + * here + * @triggers hello + * world + * foo + * bar baz + */ + public function descriptionIndentWithTags() {} } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed index 94dee74b..43d5445f 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed +++ b/test/Sniffs/Commenting/DocCommentUnitTest.inc.fixed @@ -178,7 +178,7 @@ $c = 'xyz'; /** * @todo: comment * next line - * another one + * another one * * @return void The description * extra line here @@ -248,4 +248,18 @@ $c = 'xyz'; * @see */ private function emptySeeContent() {} + + /** + * @triggers Comment here + * and continuation here + * and here + * @triggers Something + * else + * here + * @triggers hello + * world + * foo + * bar baz + */ + public function descriptionIndentWithTags() {} } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.php b/test/Sniffs/Commenting/DocCommentUnitTest.php index 46583dac..f62f706e 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.php +++ b/test/Sniffs/Commenting/DocCommentUnitTest.php @@ -169,6 +169,13 @@ public function getErrorList($testFile = '') 236 => 1, 241 => 1, 246 => 1, + 252 => 1, + 253 => 1, + 255 => 1, + 256 => 1, + 258 => 1, + 259 => 1, + 260 => 1, ]; } From 15b4fdb4218781f1b57b763c6952d606b574dbec Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 8 Mar 2018 08:52:49 +0000 Subject: [PATCH 195/225] Do not use "parent" as param type hint/return type in interfaces --- src/ZendCodingStandard/Helper/Methods.php | 8 ++++---- .../Commenting/TagWithTypeUnitTest.1.inc | 18 ++++++++++++++++++ .../Commenting/TagWithTypeUnitTest.1.inc.fixed | 18 ++++++++++++++++++ .../Commenting/TagWithTypeUnitTest.2.inc | 18 ++++++++++++++++++ .../Commenting/TagWithTypeUnitTest.2.inc.fixed | 18 ++++++++++++++++++ test/Sniffs/Commenting/TagWithTypeUnitTest.php | 2 ++ test/Sniffs/Functions/ParamUnitTest.inc | 9 +++++++++ test/Sniffs/Functions/ParamUnitTest.inc.fixed | 9 +++++++++ test/Sniffs/Functions/ParamUnitTest.php | 1 + test/Sniffs/Functions/ReturnTypeUnitTest.1.inc | 9 +++++++++ .../Functions/ReturnTypeUnitTest.1.inc.fixed | 9 +++++++++ test/Sniffs/Functions/ReturnTypeUnitTest.php | 1 + 12 files changed, 116 insertions(+), 4 deletions(-) diff --git a/src/ZendCodingStandard/Helper/Methods.php b/src/ZendCodingStandard/Helper/Methods.php index 4c4d3c3b..741d1895 100644 --- a/src/ZendCodingStandard/Helper/Methods.php +++ b/src/ZendCodingStandard/Helper/Methods.php @@ -26,12 +26,10 @@ use function strtr; use function substr; -use const T_CLASS; use const T_DOC_COMMENT_CLOSE_TAG; use const T_DOC_COMMENT_TAG; use const T_DOC_COMMENT_WHITESPACE; use const T_INTERFACE; -use const T_TRAIT; use const T_WHITESPACE; /** @@ -155,10 +153,12 @@ private function initScope(File $phpcsFile, int $stackPtr) : void $this->implementedInterfaceNames = []; if ($tokens[$stackPtr]['conditions']) { $conditionCode = end($tokens[$stackPtr]['conditions']); - if (in_array($conditionCode, [T_CLASS, T_TRAIT, T_INTERFACE], true)) { + if (in_array($conditionCode, Tokens::$ooScopeTokens, true)) { $conditionPtr = key($tokens[$stackPtr]['conditions']); $this->className = $phpcsFile->getDeclarationName($conditionPtr); - $this->parentClassName = $phpcsFile->findExtendedClassName($conditionPtr) ?: null; + if ($conditionCode !== T_INTERFACE) { + $this->parentClassName = $phpcsFile->findExtendedClassName($conditionPtr) ?: null; + } $this->implementedInterfaceNames = $phpcsFile->findImplementedInterfaceNames($conditionPtr) ?: []; } } diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc b/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc index d354e040..18cd8aed 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc @@ -297,3 +297,21 @@ class ParamTag extends ParamTagParent { */ public function test($a, $b) {} } + +interface MyInterface extends MyOne, MyTwo +{ + /** + * @param MyInterface $self + */ + public function method1($self); + + /** + * @param MyOne $myOne + */ + public function method2($myOne); + + /** + * @param MyTwo $myTwo + */ + public function method3($myTwo); +} diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc.fixed b/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc.fixed index be665ae4..5ded053b 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc.fixed +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc.fixed @@ -297,3 +297,21 @@ class ParamTag extends ParamTagParent { */ public function test($a, $b) {} } + +interface MyInterface extends MyOne, MyTwo +{ + /** + * @param MyInterface $self + */ + public function method1($self); + + /** + * @param MyOne $myOne + */ + public function method2($myOne); + + /** + * @param MyTwo $myTwo + */ + public function method3($myTwo); +} diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc b/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc index 4ecdb865..b4f227d2 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc @@ -349,3 +349,21 @@ class ReturnTag extends ReturnTagParent { */ public function test() {} } + +interface MyInterface extends MyOne, MyTwo +{ + /** + * @return MyInterface + */ + public function method1($self); + + /** + * @return MyOne + */ + public function method2($myOne); + + /** + * @return MyTwo + */ + public function method3($myTwo); +} diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc.fixed b/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc.fixed index 3d27590f..e2e3c734 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc.fixed +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc.fixed @@ -349,3 +349,21 @@ class ReturnTag extends ReturnTagParent { */ public function test() {} } + +interface MyInterface extends MyOne, MyTwo +{ + /** + * @return MyInterface + */ + public function method1($self); + + /** + * @return MyOne + */ + public function method2($myOne); + + /** + * @return MyTwo + */ + public function method3($myTwo); +} diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.php b/test/Sniffs/Commenting/TagWithTypeUnitTest.php index 71c6e45b..e94bf57b 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.php +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.php @@ -63,6 +63,7 @@ public function getErrorList($testFile = '') 272 => 1, 277 => 1, 282 => 1, + 304 => 1, ]; case 'TagWithTypeUnitTest.2.inc': return [ @@ -120,6 +121,7 @@ public function getErrorList($testFile = '') 327 => 1, 332 => 1, 337 => 1, + 356 => 1, ]; case 'TagWithTypeUnitTest.3.inc': return [ diff --git a/test/Sniffs/Functions/ParamUnitTest.inc b/test/Sniffs/Functions/ParamUnitTest.inc index 985f727e..d916a60a 100644 --- a/test/Sniffs/Functions/ParamUnitTest.inc +++ b/test/Sniffs/Functions/ParamUnitTest.inc @@ -258,3 +258,12 @@ class FunctionParam extends FunctionParamParent private function privateMethod(CALLABLE $o, Array $p) {} } + +interface MyInterface extends MyOne, MyTwo +{ + public function method1(MyInterface $self); + + public function method2(MyOne $myOne); + + public function method3(MyTwo $myTwo); +} diff --git a/test/Sniffs/Functions/ParamUnitTest.inc.fixed b/test/Sniffs/Functions/ParamUnitTest.inc.fixed index ec7ff2dc..8f7fe809 100644 --- a/test/Sniffs/Functions/ParamUnitTest.inc.fixed +++ b/test/Sniffs/Functions/ParamUnitTest.inc.fixed @@ -258,3 +258,12 @@ class FunctionParam extends FunctionParamParent private function privateMethod(callable $o, array $p) {} } + +interface MyInterface extends MyOne, MyTwo +{ + public function method1(self $self); + + public function method2(MyOne $myOne); + + public function method3(MyTwo $myTwo); +} diff --git a/test/Sniffs/Functions/ParamUnitTest.php b/test/Sniffs/Functions/ParamUnitTest.php index 25f611b0..d63db7f3 100644 --- a/test/Sniffs/Functions/ParamUnitTest.php +++ b/test/Sniffs/Functions/ParamUnitTest.php @@ -82,6 +82,7 @@ public function getErrorList($testFile = '') 243 => 1, 248 => 1, 259 => 2, + 264 => 1, ]; } diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc b/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc index a72e2c5d..d13ad345 100644 --- a/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc @@ -298,3 +298,12 @@ abstract class FunctionCommentReturn extends ParentClass */ abstract public function returnTypePrimitiveDoesNotMatchWithTag2() : string; } + +interface MyInterface extends MyOne, MyTwo +{ + public function method1($self) : MyInterface; + + public function method2($myOne) : MyOne; + + public function method3($myTwo) : MyTwo; +} diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc.fixed b/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc.fixed index ad7ed322..83a7a35b 100644 --- a/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc.fixed +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.1.inc.fixed @@ -298,3 +298,12 @@ abstract class FunctionCommentReturn extends ParentClass */ abstract public function returnTypePrimitiveDoesNotMatchWithTag2() : string; } + +interface MyInterface extends MyOne, MyTwo +{ + public function method1($self) : self; + + public function method2($myOne) : MyOne; + + public function method3($myTwo) : MyTwo; +} diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.php b/test/Sniffs/Functions/ReturnTypeUnitTest.php index 858b8a7a..0e7a13bb 100644 --- a/test/Sniffs/Functions/ReturnTypeUnitTest.php +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.php @@ -73,6 +73,7 @@ public function getErrorList($testFile = '') 287 => 2, 292 => 1, 297 => 1, + 304 => 1, ]; case 'ReturnTypeUnitTest.2.inc': return [ From 176771d0ea4ab6c305c5e1f3bc9481e0404220d1 Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 9 Mar 2018 12:55:10 +0000 Subject: [PATCH 196/225] Fixed loading imported classes/functions/constants --- src/ZendCodingStandard/Helper/Namespaces.php | 121 ++++++++++++------- 1 file changed, 78 insertions(+), 43 deletions(-) diff --git a/src/ZendCodingStandard/Helper/Namespaces.php b/src/ZendCodingStandard/Helper/Namespaces.php index 1fb6f985..c7c18e9d 100644 --- a/src/ZendCodingStandard/Helper/Namespaces.php +++ b/src/ZendCodingStandard/Helper/Namespaces.php @@ -8,6 +8,7 @@ use PHP_CodeSniffer\Util\Tokens; use ZendCodingStandard\CodingStandard; +use function in_array; use function ltrim; use function strrchr; use function strtolower; @@ -64,7 +65,13 @@ private function getGlobalUses(File $phpcsFile, int $stackPtr = 0) : array continue; } - $nextToken = $phpcsFile->findNext(T_WHITESPACE, $use + 1, null, true); + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, $use + 1, null, true); + + if ($tokens[$nextToken]['code'] === T_STRING + && in_array(strtolower($tokens[$nextToken]['content']), ['const', 'function'], true) + ) { + continue; + } $end = $phpcsFile->findNext( [T_NS_SEPARATOR, T_STRING], @@ -92,6 +99,40 @@ private function getGlobalUses(File $phpcsFile, int $stackPtr = 0) : array return $imports; } + /** + * @return false|int + */ + private function isFunctionUse(File $phpcsFile, int $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); + + if ($tokens[$next]['code'] === T_STRING + && strtolower($tokens[$next]['content']) === 'function' + ) { + return $next; + } + + return false; + } + + /** + * @return false|int + */ + private function isConstUse(File $phpcsFile, int $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); + + if ($tokens[$next]['code'] === T_STRING + && strtolower($tokens[$next]['content']) === 'const' + ) { + return $next; + } + + return false; + } + /** * @return string[][] */ @@ -113,27 +154,24 @@ private function getImportedConstants(File $phpcsFile, int $stackPtr, ?int &$las $use = $first; while ($use = $phpcsFile->findNext(T_USE, $use + 1, $last)) { - if (CodingStandard::isGlobalUse($phpcsFile, $use)) { - $next = $phpcsFile->findNext(Tokens::$emptyTokens, $use + 1, null, true); - if ($tokens[$next]['code'] === T_STRING - && strtolower($tokens[$next]['content']) === 'const' - ) { - $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); - $end = $phpcsFile->findPrevious( - T_STRING, - $phpcsFile->findNext([T_AS, T_SEMICOLON], $start + 1) - 1 - ); - $endOfStatement = $phpcsFile->findEndOfStatement($next); - $name = $phpcsFile->findPrevious(T_STRING, $endOfStatement - 1); - $fullName = $phpcsFile->getTokensAsString($start, $end - $start + 1); - - $constants[strtoupper($tokens[$name]['content'])] = [ - 'name' => $tokens[$name]['content'], - 'fqn' => ltrim($fullName, '\\'), - ]; - - $lastUse = $use; - } + if (CodingStandard::isGlobalUse($phpcsFile, $use) + && ($next = $this->isConstUse($phpcsFile, $use)) + ) { + $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); + $end = $phpcsFile->findPrevious( + T_STRING, + $phpcsFile->findNext([T_AS, T_SEMICOLON], $start + 1) - 1 + ); + $endOfStatement = $phpcsFile->findEndOfStatement($next); + $name = $phpcsFile->findPrevious(T_STRING, $endOfStatement - 1); + $fullName = $phpcsFile->getTokensAsString($start, $end - $start + 1); + + $constants[strtoupper($tokens[$name]['content'])] = [ + 'name' => $tokens[$name]['content'], + 'fqn' => ltrim($fullName, '\\'), + ]; + + $lastUse = $use; } if (! $lastUse) { @@ -165,27 +203,24 @@ private function getImportedFunctions(File $phpcsFile, int $stackPtr, ?int &$las $use = $first; while ($use = $phpcsFile->findNext(T_USE, $use + 1, $last)) { - if (CodingStandard::isGlobalUse($phpcsFile, $use)) { - $next = $phpcsFile->findNext(Tokens::$emptyTokens, $use + 1, null, true); - if ($tokens[$next]['code'] === T_STRING - && strtolower($tokens[$next]['content']) === 'function' - ) { - $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); - $end = $phpcsFile->findPrevious( - T_STRING, - $phpcsFile->findNext([T_AS, T_SEMICOLON], $start + 1) - 1 - ); - $endOfStatement = $phpcsFile->findEndOfStatement($next); - $name = $phpcsFile->findPrevious(T_STRING, $endOfStatement - 1); - $fullName = $phpcsFile->getTokensAsString($start, $end - $start + 1); - - $functions[strtolower($tokens[$name]['content'])] = [ - 'name' => $tokens[$name]['content'], - 'fqn' => ltrim($fullName, '\\'), - ]; - - $lastUse = $use; - } + if (CodingStandard::isGlobalUse($phpcsFile, $use) + && ($next = $this->isFunctionUse($phpcsFile, $use)) + ) { + $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); + $end = $phpcsFile->findPrevious( + T_STRING, + $phpcsFile->findNext([T_AS, T_SEMICOLON], $start + 1) - 1 + ); + $endOfStatement = $phpcsFile->findEndOfStatement($next); + $name = $phpcsFile->findPrevious(T_STRING, $endOfStatement - 1); + $fullName = $phpcsFile->getTokensAsString($start, $end - $start + 1); + + $functions[strtolower($tokens[$name]['content'])] = [ + 'name' => $tokens[$name]['content'], + 'fqn' => ltrim($fullName, '\\'), + ]; + + $lastUse = $use; } if (! $lastUse) { From f8795bc2b6c598a117b2f1c686974e111ac7dbf7 Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 9 Mar 2018 12:55:35 +0000 Subject: [PATCH 197/225] Better suggestion for class names (type hints, params, vars, throws, ...) --- src/ZendCodingStandard/Helper/Methods.php | 9 +++++++++ test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc | 5 +++++ test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc.fixed | 5 +++++ test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc | 5 +++++ test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc.fixed | 5 +++++ test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc | 8 ++++++++ test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc.fixed | 8 ++++++++ test/Sniffs/Commenting/TagWithTypeUnitTest.php | 8 ++++++-- test/Sniffs/Functions/ParamUnitTest.inc | 2 ++ test/Sniffs/Functions/ParamUnitTest.inc.fixed | 2 ++ test/Sniffs/Functions/ParamUnitTest.php | 3 ++- test/Sniffs/Functions/ThrowsUnitTest.inc | 8 ++++++++ test/Sniffs/Functions/ThrowsUnitTest.php | 1 + 13 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/ZendCodingStandard/Helper/Methods.php b/src/ZendCodingStandard/Helper/Methods.php index 741d1895..460bcdc0 100644 --- a/src/ZendCodingStandard/Helper/Methods.php +++ b/src/ZendCodingStandard/Helper/Methods.php @@ -20,6 +20,8 @@ use function preg_replace; use function str_replace; use function strcmp; +use function stripos; +use function strlen; use function strpos; use function strstr; use function strtolower; @@ -246,6 +248,13 @@ private function getSuggestedType(string $class) : string if (strtolower($use['class']) === $ltrim) { return $prefix . $use['alias'] . $suffix; } + + if (stripos($ltrim, $use['class'] . '\\') === 0) { + $clear = ltrim(strtr($class, ['?' => '', '[' => '', ']' => '']), '\\'); + $name = substr($clear, strlen($use['class'])); + + return $prefix . $use['alias'] . $name . $suffix; + } } } diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc b/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc index 18cd8aed..36e48549 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc @@ -296,6 +296,11 @@ class ParamTag extends ParamTagParent { * } */ public function test($a, $b) {} + + /** + * @param \RuntimeException\Hello $a Description. + */ + public function test($a) {} } interface MyInterface extends MyOne, MyTwo diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc.fixed b/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc.fixed index 5ded053b..be3bee10 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc.fixed +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.1.inc.fixed @@ -296,6 +296,11 @@ class ParamTag extends ParamTagParent { * } */ public function test($a, $b) {} + + /** + * @param Exception\Hello $a Description. + */ + public function test($a) {} } interface MyInterface extends MyOne, MyTwo diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc b/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc index b4f227d2..9494c0aa 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc @@ -348,6 +348,11 @@ class ReturnTag extends ReturnTagParent { * } */ public function test() {} + + /** + * @return \RuntimeException\Hello Description. + */ + public function test() {} } interface MyInterface extends MyOne, MyTwo diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc.fixed b/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc.fixed index e2e3c734..1bbed0ed 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc.fixed +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.2.inc.fixed @@ -348,6 +348,11 @@ class ReturnTag extends ReturnTagParent { * } */ public function test() {} + + /** + * @return Exception\Hello Description. + */ + public function test() {} } interface MyInterface extends MyOne, MyTwo diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc b/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc index aece4ed8..be933ebf 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc @@ -295,5 +295,13 @@ class VarTag extends VarTagParent { /** @var bool $a */ private $a; }; + + /** @var \RuntimeException\Hello $a Description. */ + $a = 'hello'; } + + /** + * @var \RuntimeException\Hello Description. + */ + public $a; } diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc.fixed b/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc.fixed index d70fd95d..3ed0e9b8 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc.fixed +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.3.inc.fixed @@ -295,5 +295,13 @@ class VarTag extends VarTagParent { /** @var bool */ private $a; }; + + /** @var Exception\Hello $a Description. */ + $a = 'hello'; } + + /** + * @var Exception\Hello Description. + */ + public $a; } diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.php b/test/Sniffs/Commenting/TagWithTypeUnitTest.php index e94bf57b..cdc70f19 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.php +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.php @@ -63,7 +63,8 @@ public function getErrorList($testFile = '') 272 => 1, 277 => 1, 282 => 1, - 304 => 1, + 301 => 1, + 309 => 1, ]; case 'TagWithTypeUnitTest.2.inc': return [ @@ -121,7 +122,8 @@ public function getErrorList($testFile = '') 327 => 1, 332 => 1, 337 => 1, - 356 => 1, + 353 => 1, + 361 => 1, ]; case 'TagWithTypeUnitTest.3.inc': return [ @@ -175,6 +177,8 @@ public function getErrorList($testFile = '') 282 => 1, 290 => 1, 295 => 1, + 299 => 1, + 304 => 1, ]; } diff --git a/test/Sniffs/Functions/ParamUnitTest.inc b/test/Sniffs/Functions/ParamUnitTest.inc index d916a60a..d8ceb01d 100644 --- a/test/Sniffs/Functions/ParamUnitTest.inc +++ b/test/Sniffs/Functions/ParamUnitTest.inc @@ -257,6 +257,8 @@ class FunctionParam extends FunctionParamParent public function generatorDoesNotNeedSpecificationInDocs($a) {} private function privateMethod(CALLABLE $o, Array $p) {} + + private function fqcnParam(\RuntimeException\Hello $world) {} } interface MyInterface extends MyOne, MyTwo diff --git a/test/Sniffs/Functions/ParamUnitTest.inc.fixed b/test/Sniffs/Functions/ParamUnitTest.inc.fixed index 8f7fe809..271cc07f 100644 --- a/test/Sniffs/Functions/ParamUnitTest.inc.fixed +++ b/test/Sniffs/Functions/ParamUnitTest.inc.fixed @@ -257,6 +257,8 @@ class FunctionParam extends FunctionParamParent public function generatorDoesNotNeedSpecificationInDocs($a) {} private function privateMethod(callable $o, array $p) {} + + private function fqcnParam(Exception\Hello $world) {} } interface MyInterface extends MyOne, MyTwo diff --git a/test/Sniffs/Functions/ParamUnitTest.php b/test/Sniffs/Functions/ParamUnitTest.php index d63db7f3..f4474eb7 100644 --- a/test/Sniffs/Functions/ParamUnitTest.php +++ b/test/Sniffs/Functions/ParamUnitTest.php @@ -82,7 +82,8 @@ public function getErrorList($testFile = '') 243 => 1, 248 => 1, 259 => 2, - 264 => 1, + 261 => 1, + 266 => 1, ]; } diff --git a/test/Sniffs/Functions/ThrowsUnitTest.inc b/test/Sniffs/Functions/ThrowsUnitTest.inc index ae1b265c..c4b1278a 100644 --- a/test/Sniffs/Functions/ThrowsUnitTest.inc +++ b/test/Sniffs/Functions/ThrowsUnitTest.inc @@ -275,4 +275,12 @@ class ThrowUnitTest } abstract public function abstractMethod(); + + /** + * @throws \RuntimeException\Exception + */ + public function throwException() + { + throw new Ex\Exception; + } } diff --git a/test/Sniffs/Functions/ThrowsUnitTest.php b/test/Sniffs/Functions/ThrowsUnitTest.php index 3c37e3a9..5503ac91 100644 --- a/test/Sniffs/Functions/ThrowsUnitTest.php +++ b/test/Sniffs/Functions/ThrowsUnitTest.php @@ -32,6 +32,7 @@ public function getErrorList($testFile = '') 178 => 1, 184 => 1, 189 => 1, + 280 => 1, ]; } From 4c3f464b7135ca5c63c714e87183f36a80bfcf24 Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 9 Mar 2018 12:56:20 +0000 Subject: [PATCH 198/225] Fixed issue with removing tags with description --- src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php index 5e4e9e97..fb8bb1f5 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/TagWithTypeSniff.php @@ -100,7 +100,7 @@ public function process(File $phpcsFile, $stackPtr) return; } - $split = preg_split('/\s/', $tokens[$stackPtr + 2]['content'], 3); + $split = preg_split('/\s/', $tokens[$stackPtr + 2]['content'], 2); $this->type = array_shift($split); $this->description = trim(array_shift($split) ?: '') ?: null; From 3ac062a0f16782f5dde1fbcdd9a49476c5b4a92e Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 9 Mar 2018 12:56:36 +0000 Subject: [PATCH 199/225] Added Throws sniff fixed file --- .../Sniffs/Functions/ThrowsUnitTest.inc.fixed | 286 ++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 test/Sniffs/Functions/ThrowsUnitTest.inc.fixed diff --git a/test/Sniffs/Functions/ThrowsUnitTest.inc.fixed b/test/Sniffs/Functions/ThrowsUnitTest.inc.fixed new file mode 100644 index 00000000..ed5e03b0 --- /dev/null +++ b/test/Sniffs/Functions/ThrowsUnitTest.inc.fixed @@ -0,0 +1,286 @@ +getMessage()); + } + } + + /** + * @throws Exception + */ + public function hasThrowsTagsButDoesNotThrowAnything() + { + } + + /** + * @throws Exception + */ + abstract public function abstractCanHaveThrowsTags(); + + public function throwNewClassFromVariable() + { + $e = Exception::class; + throw new $e; + } + + /** + * @throws + */ + public function missingExceptionTypeInTag() + { + } + + public function throwExceptionFromFactory() + { + throw ExceptionFacotry::create(); + } + + public function throwVariableAndException() + { + $e = new Exception(); + throw $e; + throw new Exception(); + } + + /** + * @throws Exception + */ + public function throwVariableAndExceptionOK1() + { + $e = ExceptionFactory::createException(); + throw $e; + throw new Exception(); + } + + /** + * @throws Ex + * @throws Exception + */ + public function throwVariableAndExceptionOK2() + { + $e = ExceptionFactory::createException(); + throw $e; + throw new Exception(); + } + + /** + * @throws Exception + * @throws Ex + * @throws \InvalidArgumentException + */ + public function valid1() + { + throw new Ex(); + throw new Exception(); + throw new Ex(); + throw new \InvalidArgumentException(); + throw new Exception(); + } + + public function valid2() + { + try { + throw new Ex(); + } catch (Exception $e) { + } + } + + public function valid3() + { + return function() { + throw new Ex(); + }; + } + + /** + * @throws UnknownExceptionType + */ + public function valid4() + { + throw $this->throwException(); + } + + /** + * @throws UnknownException It cannot be determined. + */ + public function valid5() + { + $ex = ExceptionFactory::create(); + throw $ex; + } + + public function valid6() + { + return function () { + return new class { + /** + * @throws Exception + */ + public function x() { + throw new Exception(); + } + }; + }; + } + + abstract public function abstractMethod(); + + /** + * @throws Ex\Exception + */ + public function throwException() + { + throw new Ex\Exception; + } +} From fd40dd3ed07b6d396f44be5d909839de79c3a12c Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 16 Mar 2018 14:17:00 +0000 Subject: [PATCH 200/225] Import internal PHP constants and functions only in namespaced files --- .../Sniffs/PHP/ImportInternalConstantSniff.php | 16 +++++++++++++--- .../Sniffs/PHP/ImportInternalFunctionSniff.php | 16 +++++++++++++--- .../PHP/ImportInternalConstantUnitTest.3.inc | 6 ++++++ .../ImportInternalConstantUnitTest.3.inc.fixed | 6 ++++++ .../PHP/ImportInternalConstantUnitTest.inc | 2 ++ .../ImportInternalConstantUnitTest.inc.fixed | 2 ++ .../PHP/ImportInternalConstantUnitTest.php | 12 ++++++++---- .../PHP/ImportInternalFunctionUnitTest.3.inc | 11 +++++++++++ .../ImportInternalFunctionUnitTest.3.inc.fixed | 11 +++++++++++ .../PHP/ImportInternalFunctionUnitTest.inc | 2 ++ .../ImportInternalFunctionUnitTest.inc.fixed | 2 ++ .../PHP/ImportInternalFunctionUnitTest.php | 18 +++++++++++------- 12 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 test/Sniffs/PHP/ImportInternalConstantUnitTest.3.inc create mode 100644 test/Sniffs/PHP/ImportInternalConstantUnitTest.3.inc.fixed create mode 100644 test/Sniffs/PHP/ImportInternalFunctionUnitTest.3.inc create mode 100644 test/Sniffs/PHP/ImportInternalFunctionUnitTest.3.inc.fixed diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php index 1af5cae6..206633b4 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php @@ -88,7 +88,7 @@ public function process(File $phpcsFile, $stackPtr) } $namespace = $this->getNamespace($phpcsFile, $stackPtr); - if ($this->currentNamespace !== $namespace) { + if ($namespace && $this->currentNamespace !== $namespace) { $this->currentNamespace = $namespace; $this->importedConstants = $this->getImportedConstants($phpcsFile, $stackPtr, $this->lastUse); } @@ -126,7 +126,17 @@ public function process(File $phpcsFile, $stackPtr) $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] === T_NS_SEPARATOR) { - if (isset($this->importedConstants[$content])) { + if (! $namespace) { + $error = 'FQN for PHP internal constant "%s" is not needed here, file does not have defined namespace'; + $data = [ + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoNamespace', $data); + if ($fix) { + $phpcsFile->fixer->replaceToken($prev, ''); + } + } elseif (isset($this->importedConstants[$content])) { if (strtoupper($this->importedConstants[$content]['fqn']) === $content) { $error = 'FQN for PHP internal constant "%s" is not needed here, constant is already imported'; $data = [ @@ -152,7 +162,7 @@ public function process(File $phpcsFile, $stackPtr) $phpcsFile->fixer->endChangeset(); } } - } else { + } elseif ($namespace) { if (! isset($this->importedConstants[$content])) { $error = 'PHP internal constant "%s" must be imported'; $data = [ diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php index d996578c..c9f899c6 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php @@ -79,7 +79,7 @@ public function process(File $phpcsFile, $stackPtr) } $namespace = $this->getNamespace($phpcsFile, $stackPtr); - if ($this->currentNamespace !== $namespace) { + if ($namespace && $this->currentNamespace !== $namespace) { $this->currentNamespace = $namespace; $this->importedFunctions = $this->getImportedFunctions($phpcsFile, $stackPtr, $this->lastUse); } @@ -114,7 +114,17 @@ public function process(File $phpcsFile, $stackPtr) $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] === T_NS_SEPARATOR) { - if (isset($this->importedFunctions[$content])) { + if (! $namespace) { + $error = 'FQN for PHP internal function "%s" is not needed here, file does not have defined namespace'; + $data = [ + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoNamespace', $data); + if ($fix) { + $phpcsFile->fixer->replaceToken($prev, ''); + } + } elseif (isset($this->importedFunctions[$content])) { if (strtolower($this->importedFunctions[$content]['fqn']) === $content) { $error = 'FQN for PHP internal function "%s" is not needed here, function is already imported'; $data = [ @@ -140,7 +150,7 @@ public function process(File $phpcsFile, $stackPtr) $phpcsFile->fixer->endChangeset(); } } - } else { + } elseif ($namespace) { if (! isset($this->importedFunctions[$content])) { $error = 'PHP internal function "%s" must be imported'; $data = [ diff --git a/test/Sniffs/PHP/ImportInternalConstantUnitTest.3.inc b/test/Sniffs/PHP/ImportInternalConstantUnitTest.3.inc new file mode 100644 index 00000000..670735ef --- /dev/null +++ b/test/Sniffs/PHP/ImportInternalConstantUnitTest.3.inc @@ -0,0 +1,6 @@ + 1, 6 => 1, ]; + case 'ImportInternalConstantUnitTest.3.inc': + return [ + 6 => 1, + ]; } return [ - 3 => 1, 5 => 1, - 6 => 2, - 19 => 1, - 24 => 1, + 7 => 1, + 8 => 2, + 21 => 1, + 26 => 1, ]; } diff --git a/test/Sniffs/PHP/ImportInternalFunctionUnitTest.3.inc b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.3.inc new file mode 100644 index 00000000..46e7e5d3 --- /dev/null +++ b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.3.inc @@ -0,0 +1,11 @@ + 1, 9 => 1, ]; + case 'ImportInternalFunctionUnitTest.3.inc': + return [ + 6 => 1, + ]; } return [ - 3 => 1, 5 => 1, - 9 => 1, - 19 => 1, - 22 => 1, - 23 => 1, + 7 => 1, + 11 => 1, + 21 => 1, + 24 => 1, 25 => 1, 27 => 1, - 28 => 1, + 29 => 1, 30 => 1, - 31 => 1, + 32 => 1, + 33 => 1, ]; } From 0fef36c0143aec6e51adf02aac6584798c9a81fa Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 16 Mar 2018 14:36:05 +0000 Subject: [PATCH 201/225] Fixed place where imported function and constant are placed It should be always after the last global import for the namespace --- src/ZendCodingStandard/Helper/Namespaces.php | 28 ++++++++----------- .../PHP/ImportInternalConstantUnitTest.4.inc | 9 ++++++ ...ImportInternalConstantUnitTest.4.inc.fixed | 12 ++++++++ .../PHP/ImportInternalConstantUnitTest.php | 5 ++++ .../PHP/ImportInternalFunctionUnitTest.4.inc | 13 +++++++++ ...ImportInternalFunctionUnitTest.4.inc.fixed | 17 +++++++++++ .../PHP/ImportInternalFunctionUnitTest.php | 7 +++++ 7 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 test/Sniffs/PHP/ImportInternalConstantUnitTest.4.inc create mode 100644 test/Sniffs/PHP/ImportInternalConstantUnitTest.4.inc.fixed create mode 100644 test/Sniffs/PHP/ImportInternalFunctionUnitTest.4.inc create mode 100644 test/Sniffs/PHP/ImportInternalFunctionUnitTest.4.inc.fixed diff --git a/src/ZendCodingStandard/Helper/Namespaces.php b/src/ZendCodingStandard/Helper/Namespaces.php index c7c18e9d..e21072d7 100644 --- a/src/ZendCodingStandard/Helper/Namespaces.php +++ b/src/ZendCodingStandard/Helper/Namespaces.php @@ -154,9 +154,11 @@ private function getImportedConstants(File $phpcsFile, int $stackPtr, ?int &$las $use = $first; while ($use = $phpcsFile->findNext(T_USE, $use + 1, $last)) { - if (CodingStandard::isGlobalUse($phpcsFile, $use) - && ($next = $this->isConstUse($phpcsFile, $use)) - ) { + if (! CodingStandard::isGlobalUse($phpcsFile, $use)) { + continue; + } + + if ($next = $this->isConstUse($phpcsFile, $use)) { $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); $end = $phpcsFile->findPrevious( T_STRING, @@ -170,13 +172,9 @@ private function getImportedConstants(File $phpcsFile, int $stackPtr, ?int &$las 'name' => $tokens[$name]['content'], 'fqn' => ltrim($fullName, '\\'), ]; - - $lastUse = $use; } - if (! $lastUse) { - $lastUse = $use; - } + $lastUse = $use; } return $constants; @@ -203,9 +201,11 @@ private function getImportedFunctions(File $phpcsFile, int $stackPtr, ?int &$las $use = $first; while ($use = $phpcsFile->findNext(T_USE, $use + 1, $last)) { - if (CodingStandard::isGlobalUse($phpcsFile, $use) - && ($next = $this->isFunctionUse($phpcsFile, $use)) - ) { + if (! CodingStandard::isGlobalUse($phpcsFile, $use)) { + continue; + } + + if ($next = $this->isFunctionUse($phpcsFile, $use)) { $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); $end = $phpcsFile->findPrevious( T_STRING, @@ -219,13 +219,9 @@ private function getImportedFunctions(File $phpcsFile, int $stackPtr, ?int &$las 'name' => $tokens[$name]['content'], 'fqn' => ltrim($fullName, '\\'), ]; - - $lastUse = $use; } - if (! $lastUse) { - $lastUse = $use; - } + $lastUse = $use; } return $functions; diff --git a/test/Sniffs/PHP/ImportInternalConstantUnitTest.4.inc b/test/Sniffs/PHP/ImportInternalConstantUnitTest.4.inc new file mode 100644 index 00000000..a79819d6 --- /dev/null +++ b/test/Sniffs/PHP/ImportInternalConstantUnitTest.4.inc @@ -0,0 +1,9 @@ + 1, ]; + case 'ImportInternalConstantUnitTest.4.inc': + return [ + 5 => 1, + 8 => 1, + ]; } return [ diff --git a/test/Sniffs/PHP/ImportInternalFunctionUnitTest.4.inc b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.4.inc new file mode 100644 index 00000000..b02e28f1 --- /dev/null +++ b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.4.inc @@ -0,0 +1,13 @@ + 1, ]; + case 'ImportInternalFunctionUnitTest.4.inc': + return [ + 5 => 1, + 6 => 1, + 9 => 1, + 10 => 1, + ]; } return [ From 1e5fd8dbc2667fc4ec51245ce9b120de95e1d155 Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 19 Mar 2018 11:03:19 +0000 Subject: [PATCH 202/225] Fixed indents with "yield" --- .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 31 ++++++++++++++++++- .../Sniffs/WhiteSpace/ScopeIndentUnitTest.inc | 25 +++++++++++++++ .../WhiteSpace/ScopeIndentUnitTest.inc.fixed | 25 +++++++++++++++ .../Sniffs/WhiteSpace/ScopeIndentUnitTest.php | 19 ++++++++++++ 4 files changed, 99 insertions(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index e48c9601..f6fc2b97 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -32,6 +32,7 @@ use const T_CONSTANT_ENCAPSED_STRING; use const T_CONTINUE; use const T_DOC_COMMENT_OPEN_TAG; +use const T_DOUBLE_ARROW; use const T_DOUBLE_QUOTED_STRING; use const T_ELSEIF; use const T_EXIT; @@ -385,6 +386,34 @@ public function process(File $phpcsFile, $stackPtr) } } + if ($tokens[$i]['code'] === T_DOUBLE_ARROW) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $i - 1, null, true); + + if ($tokens[$prev]['line'] === $tokens[$i]['line']) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $i + 1, null, true); + + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS + && $tokens[$tokens[$next]['parenthesis_closer']]['line'] > $tokens[$next]['line'] + ) { + $after = $phpcsFile->findNext( + Tokens::$emptyTokens, + $tokens[$next]['parenthesis_closer'] + 1, + null, + true + ); + if ($tokens[$after]['code'] === T_OBJECT_OPERATOR) { + $newEI = $this->indent; + $extraIndent += $newEI; + if (isset($extras[$after])) { + $extras[$after] += $newEI; + } else { + $extras[$after] = $newEI; + } + } + } + } + } + if ($tokens[$i]['code'] === T_OBJECT_OPERATOR) { $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $i - 1, null, true); @@ -779,7 +808,7 @@ private function np(File $phpcsFile, int $ptr) : ?int $ptr = $tokens[$ptr]['bracket_closer']; } elseif (in_array( $tokens[$ptr]['code'], - [T_OBJECT_OPERATOR, T_SEMICOLON, T_CLOSE_PARENTHESIS], + [T_OBJECT_OPERATOR, T_SEMICOLON, T_CLOSE_PARENTHESIS, T_CLOSE_SHORT_ARRAY], true )) { return $ptr; diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc index 700e2872..54211edc 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc @@ -506,3 +506,28 @@ $response = $handler->handle( ->withMethod(RequestMethod::METHOD_GET) ->withAttribute(self::FORWARDED_HTTP_METHOD_ATTRIBUTE, RequestMethod::METHOD_HEAD) ); + +yield 'key' => (new DateTime( + (function () { + yield 'key1' => (new X( + 'hi' + )); + + yield 'key2' => (new X( + 'hi', + )) + ->m() + ->r(); + + yield 'key3' => function () { + return [ + 'arr' => (new X( + 'hello' + )) + ->m() + ->s(), + ]; + }; + })() +)) +->format('Y'); diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed index dc3b698a..934d5e58 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed @@ -504,3 +504,28 @@ $response = $handler->handle( ->withMethod(RequestMethod::METHOD_GET) ->withAttribute(self::FORWARDED_HTTP_METHOD_ATTRIBUTE, RequestMethod::METHOD_HEAD) ); + +yield 'key' => (new DateTime( + (function () { + yield 'key1' => (new X( + 'hi' + )); + + yield 'key2' => (new X( + 'hi', + )) + ->m() + ->r(); + + yield 'key3' => function () { + return [ + 'arr' => (new X( + 'hello' + )) + ->m() + ->s(), + ]; + }; + })() + )) + ->format('Y'); diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php index e5567733..da6dacaa 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php @@ -238,6 +238,25 @@ public function getErrorList($testFile = '') 475 => 1, 477 => 1, 478 => 1, + 511 => 1, + 512 => 1, + 513 => 1, + 514 => 1, + 516 => 1, + 517 => 1, + 518 => 1, + 519 => 1, + 522 => 1, + 523 => 1, + 524 => 1, + 525 => 1, + 526 => 1, + 527 => 1, + 529 => 1, + 530 => 1, + 531 => 1, + 532 => 1, + 533 => 1, ]; } From 12a083ad200cc64dec848df5eddfba782f79d77b Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 27 Mar 2018 14:31:43 +0100 Subject: [PATCH 203/225] Added DeclareStrictTypes sniff Originally I created PR with this sniff to PHP_CodeSniffer but as it is delayed there I'm adding it here. When it will be available in PHP_CodeSniffer we can use it. --- .../Sniffs/PHP/DeclareStrictTypesSniff.php | 379 ++++++++++++++++++ .../PHP/DeclareStrictTypesUnitTest.1.inc | 7 + .../DeclareStrictTypesUnitTest.1.inc.fixed | 8 + .../PHP/DeclareStrictTypesUnitTest.10.inc | 4 + .../DeclareStrictTypesUnitTest.10.inc.fixed | 6 + .../PHP/DeclareStrictTypesUnitTest.11.inc | 12 + .../DeclareStrictTypesUnitTest.11.inc.fixed | 12 + .../PHP/DeclareStrictTypesUnitTest.12.inc | 6 + .../DeclareStrictTypesUnitTest.12.inc.fixed | 8 + .../PHP/DeclareStrictTypesUnitTest.13.inc | 2 + .../DeclareStrictTypesUnitTest.13.inc.fixed | 3 + .../PHP/DeclareStrictTypesUnitTest.2.inc | 2 + .../DeclareStrictTypesUnitTest.2.inc.fixed | 3 + .../PHP/DeclareStrictTypesUnitTest.3.inc | 8 + .../DeclareStrictTypesUnitTest.3.inc.fixed | 7 + .../PHP/DeclareStrictTypesUnitTest.4.inc | 2 + .../DeclareStrictTypesUnitTest.4.inc.fixed | 5 + .../PHP/DeclareStrictTypesUnitTest.5.inc | 2 + .../DeclareStrictTypesUnitTest.5.inc.fixed | 3 + .../PHP/DeclareStrictTypesUnitTest.6.inc | 8 + .../DeclareStrictTypesUnitTest.6.inc.fixed | 8 + .../PHP/DeclareStrictTypesUnitTest.7.inc | 13 + .../DeclareStrictTypesUnitTest.7.inc.fixed | 8 + .../PHP/DeclareStrictTypesUnitTest.8.inc | 15 + .../DeclareStrictTypesUnitTest.8.inc.fixed | 14 + .../PHP/DeclareStrictTypesUnitTest.9.inc | 1 + .../DeclareStrictTypesUnitTest.9.inc.fixed | 5 + .../Sniffs/PHP/DeclareStrictTypesUnitTest.inc | 8 + .../PHP/DeclareStrictTypesUnitTest.inc.fixed | 5 + .../Sniffs/PHP/DeclareStrictTypesUnitTest.php | 69 ++++ 30 files changed, 633 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/PHP/DeclareStrictTypesSniff.php create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.1.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.1.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.10.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.10.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.11.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.11.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.12.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.12.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.13.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.13.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.2.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.2.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.3.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.3.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.4.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.4.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.5.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.5.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.6.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.6.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.7.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.7.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.8.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.8.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.9.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.9.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.inc create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.inc.fixed create mode 100644 test/Sniffs/PHP/DeclareStrictTypesUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/PHP/DeclareStrictTypesSniff.php b/src/ZendCodingStandard/Sniffs/PHP/DeclareStrictTypesSniff.php new file mode 100644 index 00000000..9e153954 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/PHP/DeclareStrictTypesSniff.php @@ -0,0 +1,379 @@ +spacingBefore = (int) $this->spacingBefore; + $this->spacingAfter = (int) $this->spacingAfter; + + $tokens = $phpcsFile->getTokens(); + + if ($stackPtr > 0) { + $before = trim($phpcsFile->getTokensAsString(0, $stackPtr)); + + if ($before === '') { + $error = 'Unexpected whitespace before PHP opening tag'; + $fix = $phpcsFile->addFixableError($error, 0, 'Whitespace'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = 0; $i < $stackPtr; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $error = 'Missing strict type declaration as first statement in the script'; + $fix = $phpcsFile->addFixableError($error, 0, 'Missing'); + + if ($fix) { + $phpcsFile->fixer->addContentBefore( + 0, + sprintf('%s', $this->format, $phpcsFile->eolChar) + ); + } + } + + $this->checkOtherDeclarations($phpcsFile); + + return $phpcsFile->numTokens; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); + + if ($tokens[$next]['code'] === T_DECLARE) { + $string = $phpcsFile->findNext( + T_STRING, + $tokens[$next]['parenthesis_opener'] + 1, + $tokens[$next]['parenthesis_closer'] + ); + + if ($string !== false + && stripos($tokens[$string]['content'], 'strict_types') !== false + ) { + $eos = $phpcsFile->findEndOfStatement($next); + $prev = $phpcsFile->findPrevious(T_WHITESPACE, $next - 1, null, true); + $after = $phpcsFile->findNext(T_WHITESPACE, $eos + 1, null, true); + + if ($after !== false + && $tokens[$prev]['code'] === T_OPEN_TAG + && $tokens[$after]['code'] === T_CLOSE_TAG + ) { + if ($tokens[$prev]['line'] !== $tokens[$next]['line']) { + $error = 'PHP open tag must be on the same line as strict type declaration.'; + $fix = $phpcsFile->addFixableError($error, $prev, 'OpenTag'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($prev, 'fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + $prev = false; + } + + if ($prev !== false && ($prev < ($next - 1) || $tokens[$prev]['content'] !== 'addFixableError($error, $prev, 'OpenTagSpace'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($prev, 'fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + if ($tokens[$after]['line'] !== $tokens[$eos]['line']) { + $error = 'PHP close tag must be on the same line as strict type declaration.'; + $fix = $phpcsFile->addFixableError($error, $after, 'CloseTag'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $eos + 1; $i < $after; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContentBefore($after, ' '); + $phpcsFile->fixer->endChangeset(); + } + + $after = false; + } + + if ($after !== false && ($after > $eos + 2 || $tokens[$eos + 1]['content'] !== ' ')) { + $error = 'Expected single space before PHP close tag and after declaration.'; + $fix = $phpcsFile->addFixableError($error, $after, 'CloseTagSpace'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $eos + 1; $i < $after; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContentBefore($after, ' '); + $phpcsFile->fixer->endChangeset(); + } + } + + $prev = false; + $after = false; + } + + // Check how many blank lines there are before declare statement. + if ($prev !== false) { + $linesBefore = $tokens[$next]['line'] - $tokens[$prev]['line'] - 1; + if ($linesBefore !== $this->spacingBefore) { + if ($linesBefore < 0) { + $error = 'Strict type declaration must be in new line'; + $data = []; + } else { + $error = 'Invalid number of blank lines before declare statement;' + . ' expected %d, but found %d'; + $data = [ + $this->spacingBefore, + $linesBefore, + ]; + } + + $fix = $phpcsFile->addFixableError($error, $next, 'LinesBefore', $data); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + if ($linesBefore > $this->spacingBefore) { + // Remove additional blank line(s). + for ($i = $prev + 1; $i < $next; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + if ($tokens[$next]['line'] - $tokens[$i + 1]['line'] - 1 === $this->spacingBefore) { + break; + } + } + } else { + // Clear whitespaces between prev and next, but no new lines. + if ($linesBefore < 0) { + for ($i = $prev + 1; $i < $next; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + // Add new blank line(s). + while ($linesBefore < $this->spacingBefore) { + $phpcsFile->fixer->addNewlineBefore($next); + ++$linesBefore; + } + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + + // Check number of blank lines after the declare statement. + if ($after !== false) { + if ($tokens[$after]['code'] === T_CLOSE_TAG) { + $this->spacingAfter = 0; + } + + $linesAfter = $tokens[$after]['line'] - $tokens[$eos]['line'] - 1; + if ($linesAfter !== $this->spacingAfter) { + if ($linesAfter < 0) { + $error = 'Strict type declaration must be the only statement in the line'; + $data = []; + } else { + $error = 'Invalid number of blank lines after declare statement; expected %d, but found %d'; + $data = [ + $this->spacingAfter, + $linesAfter, + ]; + } + + $fix = $phpcsFile->addFixableError($error, $eos, 'LinesAfter', $data); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + if ($linesAfter > $this->spacingAfter) { + for ($i = $eos + 1; $i < $after; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + if ($tokens[$after]['line'] - $tokens[$i + 1]['line'] - 1 === $this->spacingAfter) { + break; + } + } + } else { + // Remove whitespaces between EOS and after token. + if ($linesAfter < 0) { + for ($i = $eos + 1; $i < $after; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + // Add new lines after the statement. + while ($linesAfter < $this->spacingAfter) { + $phpcsFile->fixer->addNewline($eos); + ++$linesAfter; + } + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + + // Check if declare statement match provided format. + $string = $phpcsFile->getTokensAsString($next, $eos - $next + 1); + if ($string !== $this->format) { + $error = 'Invalid format of strict type declaration; expected "%s", but found "%s"'; + $data = [ + $this->format, + $string, + ]; + + if ($this->normalize($string) === $this->normalize($this->format)) { + $fix = $phpcsFile->addFixableError($error, $next, 'InvalidFormat', $data); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $next; $i < $eos; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken($eos, $this->format); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError($error, $next, 'InvalidFormatNotFixable', $data); + } + } + + $this->checkOtherDeclarations($phpcsFile, $next); + + return $phpcsFile->numTokens; + } + } + + $this->checkOtherDeclarations($phpcsFile, $next); + + $error = 'Missing strict type declaration at the beginning of the file'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotFound'); + + if ($fix) { + $phpcsFile->fixer->addContent($stackPtr, $this->format . $phpcsFile->eolChar); + } + + return $phpcsFile->numTokens; + } + + /** + * @param string $string String to be normalized. + */ + private function normalize(string $string) : string + { + return strtolower(preg_replace('/\s/', '', $string)); + } + + /** + * Process other strict_type declaration in the file and remove them. + * The declaration has to be the very first statement in the script. + * + * @param File $phpcsFile The file being scanned. + * @param int $declare The position of the first declaration. + */ + private function checkOtherDeclarations(File $phpcsFile, int $declare = 0) : void + { + $tokens = $phpcsFile->getTokens(); + + while ($declare = $phpcsFile->findNext(T_DECLARE, $declare + 1)) { + $string = $phpcsFile->findNext( + T_STRING, + $tokens[$declare]['parenthesis_opener'] + 1, + $tokens[$declare]['parenthesis_closer'] + ); + + if ($string !== false + && stripos($tokens[$string]['content'], 'strict_types') !== false + ) { + $error = 'Strict type declaration must be the very first statement in the script'; + $fix = $phpcsFile->addFixableError($error, $declare, 'NotFirstStatement'); + + if ($fix) { + $end = $phpcsFile->findNext( + Tokens::$emptyTokens + [T_SEMICOLON => T_SEMICOLON], + $tokens[$declare]['parenthesis_closer'] + 1, + null, + true + ); + + if ($end === false) { + $end = $phpcsFile->numTokens; + } + + for ($i = $declare; $i < $end; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } + } + } +} diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.1.inc b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.1.inc new file mode 100644 index 00000000..ed04879a --- /dev/null +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.1.inc @@ -0,0 +1,7 @@ + + + + <?php + declare(strict_types=1); + echo 'Title'; + ?> + + + + + diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.11.inc.fixed b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.11.inc.fixed new file mode 100644 index 00000000..cfad003b --- /dev/null +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.11.inc.fixed @@ -0,0 +1,12 @@ + + + + + <?php + echo 'Title'; + ?> + + + + + diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.12.inc b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.12.inc new file mode 100644 index 00000000..5ab5fb76 --- /dev/null +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.12.inc @@ -0,0 +1,6 @@ + + + + diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.12.inc.fixed b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.12.inc.fixed new file mode 100644 index 00000000..eb1c6a15 --- /dev/null +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.12.inc.fixed @@ -0,0 +1,8 @@ + + + + diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.13.inc b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.13.inc new file mode 100644 index 00000000..b5c390ae --- /dev/null +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.13.inc @@ -0,0 +1,2 @@ + + + + <?php echo 'Title'; ?> + + + + diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.6.inc.fixed b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.6.inc.fixed new file mode 100644 index 00000000..468d36c7 --- /dev/null +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.6.inc.fixed @@ -0,0 +1,8 @@ + + + + <?php echo 'Title'; ?> + + + + diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.7.inc b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.7.inc new file mode 100644 index 00000000..0dd39dd4 --- /dev/null +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.7.inc @@ -0,0 +1,13 @@ + + + + <?php echo 'Title'; ?> + + + + diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.7.inc.fixed b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.7.inc.fixed new file mode 100644 index 00000000..468d36c7 --- /dev/null +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.7.inc.fixed @@ -0,0 +1,8 @@ + + + + <?php echo 'Title'; ?> + + + + diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.8.inc b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.8.inc new file mode 100644 index 00000000..7d570e97 --- /dev/null +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.8.inc @@ -0,0 +1,15 @@ + + + + <?php echo 'Title'; ?> + + + + diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.8.inc.fixed b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.8.inc.fixed new file mode 100644 index 00000000..ec8ce723 --- /dev/null +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.8.inc.fixed @@ -0,0 +1,14 @@ + + + + <?php echo 'Title'; ?> + + + + diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.9.inc b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.9.inc new file mode 100644 index 00000000..6d6f8774 --- /dev/null +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.9.inc @@ -0,0 +1 @@ + diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.9.inc.fixed b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.9.inc.fixed new file mode 100644 index 00000000..2e240679 --- /dev/null +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.9.inc.fixed @@ -0,0 +1,5 @@ + diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.inc b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.inc new file mode 100644 index 00000000..7438d056 --- /dev/null +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.inc @@ -0,0 +1,8 @@ + + + 1]; + case 'DeclareStrictTypesUnitTest.2.inc': + return [2 => 1]; + case 'DeclareStrictTypesUnitTest.3.inc': + return [8 => 1]; + case 'DeclareStrictTypesUnitTest.4.inc': + return [1 => 1]; + case 'DeclareStrictTypesUnitTest.5.inc': + return [2 => 2]; + case 'DeclareStrictTypesUnitTest.6.inc': + return [1 => 2]; + case 'DeclareStrictTypesUnitTest.7.inc': + return [ + 1 => 1, + 6 => 1, + ]; + case 'DeclareStrictTypesUnitTest.8.inc': + return [6 => 1]; + case 'DeclareStrictTypesUnitTest.9.inc': + return [1 => 2]; + case 'DeclareStrictTypesUnitTest.10.inc': + return [ + 1 => 1, + 4 => 1, + ]; + case 'DeclareStrictTypesUnitTest.11.inc': + return [ + 1 => 1, + 5 => 1, + ]; + case 'DeclareStrictTypesUnitTest.12.inc': + return [3 => 2]; + case 'DeclareStrictTypesUnitTest.13.inc': + return [2 => 2]; + } + + return [ + 1 => 1, + 5 => 1, + ]; + } + + /** + * @param string $testFile + * @return int[] + */ + public function getWarningList($testFile = '') + { + return []; + } +} From 70dfc7631df1e345a3c1a1cba40ee104c43a348a Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 27 Mar 2018 14:38:03 +0100 Subject: [PATCH 204/225] Future-proof changes - tested with PHP_CodeSniffer dev-master - `AbstractVariableSniff` has now the same named protected property so we can't redefine it with private visibility - `findEndOfStatement` behaviour has been fixed, and property returns close curly brackets for statements with curly brackets --- .../Sniffs/Arrays/FormatSniff.php | 5 ++- .../ValidVariableNameSniff.php | 32 ++++++++----------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php index bbb06f08..202bb1d0 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/FormatSniff.php @@ -11,6 +11,7 @@ use function strlen; use function strpos; +use const T_CLOSE_CURLY_BRACKET; use const T_CLOSE_SHORT_ARRAY; use const T_COMMENT; use const T_DOUBLE_ARROW; @@ -152,7 +153,9 @@ protected function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $ar $end = $next; } else { $end = $phpcsFile->findEndOfStatement($next); - if ($tokens[$end]['code'] === T_DOUBLE_ARROW) { + if ($tokens[$end]['code'] === T_DOUBLE_ARROW + || $tokens[$end]['code'] === T_CLOSE_CURLY_BRACKET + ) { $end = $phpcsFile->findEndOfStatement($end); } } diff --git a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php index 6e0c9bf7..327fd6b4 100644 --- a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php +++ b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -1,9 +1,4 @@ true, + '_GET' => true, + '_POST' => true, + '_REQUEST' => true, + '_SESSION' => true, + '_ENV' => true, + '_COOKIE' => true, + '_FILES' => true, + 'GLOBALS' => true, ]; /** @@ -43,7 +39,7 @@ protected function processVariable(File $phpcsFile, $stackPtr) : void $varName = ltrim($tokens[$stackPtr]['content'], '$'); // If it's a php reserved var, then its ok. - if (in_array($varName, $this->phpReservedVars, true)) { + if (isset($this->phpReservedVars[$varName])) { return; } From 4d261c562e66379b5407cbe47a2012222c6070a6 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 27 Mar 2018 15:12:00 +0100 Subject: [PATCH 205/225] More PHP 7.1 improvements --- test/Sniffs/Arrays/FormatUnitTest.php | 12 ++---------- .../Arrays/TrailingArrayCommaUnitTest.php | 12 ++---------- .../AlphabeticallySortedTraitsUnitTest.php | 12 ++---------- .../Sniffs/Classes/ConstVisibilityUnitTest.php | 12 ++---------- test/Sniffs/Classes/NoNullValuesUnitTest.php | 12 ++---------- test/Sniffs/Classes/TraitUsageUnitTest.php | 12 ++---------- test/Sniffs/Commenting/DocCommentUnitTest.php | 12 ++---------- .../Commenting/FunctionCommentUnitTest.php | 12 ++---------- .../FunctionDataProviderTagUnitTest.php | 12 ++---------- .../FunctionDisallowedTagUnitTest.php | 12 ++---------- .../NoInlineCommentAfterCurlyCloseUnitTest.php | 12 ++---------- test/Sniffs/Commenting/TagCaseUnitTest.php | 12 ++---------- test/Sniffs/Commenting/TagWithTypeUnitTest.php | 12 ++---------- .../Commenting/VariableCommentUnitTest.php | 12 ++---------- test/Sniffs/Formatting/DoubleColonUnitTest.php | 12 ++---------- test/Sniffs/Formatting/NewKeywordUnitTest.php | 12 ++---------- .../Formatting/NoSpaceAfterSplatUnitTest.php | 12 ++---------- test/Sniffs/Formatting/ReferenceUnitTest.php | 12 ++---------- test/Sniffs/Formatting/ReturnTypeUnitTest.php | 12 ++---------- .../UnnecessaryParenthesesUnitTest.php | 12 ++---------- test/Sniffs/Functions/ParamUnitTest.php | 12 ++---------- test/Sniffs/Functions/ReturnTypeUnitTest.php | 12 ++---------- test/Sniffs/Functions/ThrowsUnitTest.php | 12 ++---------- test/Sniffs/Methods/LineAfterUnitTest.php | 12 ++---------- .../AlphabeticallySortedUsesUnitTest.php | 12 ++---------- .../ConstAndFunctionKeywordsUnitTest.php | 12 ++---------- .../Namespaces/UnusedUseStatementUnitTest.php | 12 ++---------- .../UseDoesNotStartWithBackslashUnitTest.php | 12 ++---------- .../ValidVariableNameUnitTest.php | 12 ++---------- .../Operators/BooleanOperatorUnitTest.php | 12 ++---------- .../Operators/TernaryOperatorUnitTest.php | 12 ++---------- .../PHP/CorrectClassNameCaseUnitTest.php | 12 ++---------- test/Sniffs/PHP/DeclareStrictTypesUnitTest.php | 12 ++---------- .../PHP/ImportInternalConstantUnitTest.php | 12 ++---------- .../PHP/ImportInternalFunctionUnitTest.php | 12 ++---------- .../PHP/InstantiatingParenthesisUnitTest.php | 12 ++---------- test/Sniffs/PHP/RedundantSemicolonUnitTest.php | 12 ++---------- test/Sniffs/PHP/SingleSemicolonUnitTest.php | 12 ++---------- test/Sniffs/PHP/TypeCastingUnitTest.php | 12 ++---------- .../NoConcatenationAtTheEndUnitTest.php | 12 ++---------- test/Sniffs/TestCase.php | 18 ++++++++---------- test/Sniffs/WhiteSpace/BlankLineUnitTest.php | 12 ++---------- .../Sniffs/WhiteSpace/CommaSpacingUnitTest.php | 12 ++---------- .../WhiteSpace/NoBlankLineAtStartUnitTest.php | 12 ++---------- test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php | 12 ++---------- 45 files changed, 96 insertions(+), 450 deletions(-) diff --git a/test/Sniffs/Arrays/FormatUnitTest.php b/test/Sniffs/Arrays/FormatUnitTest.php index 9ad40d60..273b89d6 100644 --- a/test/Sniffs/Arrays/FormatUnitTest.php +++ b/test/Sniffs/Arrays/FormatUnitTest.php @@ -8,11 +8,7 @@ class FormatUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 2 => 2, @@ -41,11 +37,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.php b/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.php index f4c10928..bcbb5b1a 100644 --- a/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.php +++ b/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.php @@ -8,11 +8,7 @@ class TrailingArrayCommaUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 11 => 1, @@ -22,11 +18,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.php b/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.php index afc68e12..91f680d9 100644 --- a/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.php +++ b/test/Sniffs/Classes/AlphabeticallySortedTraitsUnitTest.php @@ -8,11 +8,7 @@ class AlphabeticallySortedTraitsUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 12 => 1, @@ -20,11 +16,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Classes/ConstVisibilityUnitTest.php b/test/Sniffs/Classes/ConstVisibilityUnitTest.php index 6d4ea46a..f1398936 100644 --- a/test/Sniffs/Classes/ConstVisibilityUnitTest.php +++ b/test/Sniffs/Classes/ConstVisibilityUnitTest.php @@ -8,11 +8,7 @@ class ConstVisibilityUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 6 => 1, @@ -21,11 +17,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Classes/NoNullValuesUnitTest.php b/test/Sniffs/Classes/NoNullValuesUnitTest.php index 814275cf..4a5c9347 100644 --- a/test/Sniffs/Classes/NoNullValuesUnitTest.php +++ b/test/Sniffs/Classes/NoNullValuesUnitTest.php @@ -8,11 +8,7 @@ class NoNullValuesUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 6 => 1, @@ -24,11 +20,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Classes/TraitUsageUnitTest.php b/test/Sniffs/Classes/TraitUsageUnitTest.php index 8296b2bb..1c8a2d01 100644 --- a/test/Sniffs/Classes/TraitUsageUnitTest.php +++ b/test/Sniffs/Classes/TraitUsageUnitTest.php @@ -8,11 +8,7 @@ class TraitUsageUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 9 => 1, @@ -28,11 +24,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Commenting/DocCommentUnitTest.php b/test/Sniffs/Commenting/DocCommentUnitTest.php index f62f706e..775cf13a 100644 --- a/test/Sniffs/Commenting/DocCommentUnitTest.php +++ b/test/Sniffs/Commenting/DocCommentUnitTest.php @@ -8,11 +8,7 @@ class DocCommentUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { switch ($testFile) { case 'DocCommentUnitTest.1.inc': @@ -179,11 +175,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Commenting/FunctionCommentUnitTest.php b/test/Sniffs/Commenting/FunctionCommentUnitTest.php index 32de740f..b62ae9de 100644 --- a/test/Sniffs/Commenting/FunctionCommentUnitTest.php +++ b/test/Sniffs/Commenting/FunctionCommentUnitTest.php @@ -8,11 +8,7 @@ class FunctionCommentUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 7 => 1, @@ -31,11 +27,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Commenting/FunctionDataProviderTagUnitTest.php b/test/Sniffs/Commenting/FunctionDataProviderTagUnitTest.php index 1de63364..53f6d0dd 100644 --- a/test/Sniffs/Commenting/FunctionDataProviderTagUnitTest.php +++ b/test/Sniffs/Commenting/FunctionDataProviderTagUnitTest.php @@ -8,11 +8,7 @@ class FunctionDataProviderTagUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 9 => 1, @@ -22,11 +18,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Commenting/FunctionDisallowedTagUnitTest.php b/test/Sniffs/Commenting/FunctionDisallowedTagUnitTest.php index c3b2e352..eb6c5a60 100644 --- a/test/Sniffs/Commenting/FunctionDisallowedTagUnitTest.php +++ b/test/Sniffs/Commenting/FunctionDisallowedTagUnitTest.php @@ -8,11 +8,7 @@ class FunctionDisallowedTagUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 12 => 1, @@ -31,11 +27,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseUnitTest.php b/test/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseUnitTest.php index ca494052..038c01b8 100644 --- a/test/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseUnitTest.php +++ b/test/Sniffs/Commenting/NoInlineCommentAfterCurlyCloseUnitTest.php @@ -8,11 +8,7 @@ class NoInlineCommentAfterCurlyCloseUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 10 => 1, @@ -22,11 +18,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Commenting/TagCaseUnitTest.php b/test/Sniffs/Commenting/TagCaseUnitTest.php index b5c98071..d3f26186 100644 --- a/test/Sniffs/Commenting/TagCaseUnitTest.php +++ b/test/Sniffs/Commenting/TagCaseUnitTest.php @@ -8,11 +8,7 @@ class TagCaseUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 4 => 1, @@ -78,11 +74,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Commenting/TagWithTypeUnitTest.php b/test/Sniffs/Commenting/TagWithTypeUnitTest.php index cdc70f19..80b1b5d5 100644 --- a/test/Sniffs/Commenting/TagWithTypeUnitTest.php +++ b/test/Sniffs/Commenting/TagWithTypeUnitTest.php @@ -8,11 +8,7 @@ class TagWithTypeUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { switch ($testFile) { case 'TagWithTypeUnitTest.1.inc': @@ -185,11 +181,7 @@ public function getErrorList($testFile = '') return []; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Commenting/VariableCommentUnitTest.php b/test/Sniffs/Commenting/VariableCommentUnitTest.php index 7f1c8a41..5cd1d87b 100644 --- a/test/Sniffs/Commenting/VariableCommentUnitTest.php +++ b/test/Sniffs/Commenting/VariableCommentUnitTest.php @@ -8,11 +8,7 @@ class VariableCommentUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 4 => 1, @@ -26,11 +22,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Formatting/DoubleColonUnitTest.php b/test/Sniffs/Formatting/DoubleColonUnitTest.php index c9011519..01bf506c 100644 --- a/test/Sniffs/Formatting/DoubleColonUnitTest.php +++ b/test/Sniffs/Formatting/DoubleColonUnitTest.php @@ -8,11 +8,7 @@ class DoubleColonUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 4 => 2, @@ -25,11 +21,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Formatting/NewKeywordUnitTest.php b/test/Sniffs/Formatting/NewKeywordUnitTest.php index f854f66c..47e33637 100644 --- a/test/Sniffs/Formatting/NewKeywordUnitTest.php +++ b/test/Sniffs/Formatting/NewKeywordUnitTest.php @@ -8,11 +8,7 @@ class NewKeywordUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ // 3 => 1, // not checking next character after space @@ -25,11 +21,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Formatting/NoSpaceAfterSplatUnitTest.php b/test/Sniffs/Formatting/NoSpaceAfterSplatUnitTest.php index 2de82052..d7989812 100644 --- a/test/Sniffs/Formatting/NoSpaceAfterSplatUnitTest.php +++ b/test/Sniffs/Formatting/NoSpaceAfterSplatUnitTest.php @@ -8,11 +8,7 @@ class NoSpaceAfterSplatUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 3 => 1, @@ -23,11 +19,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Formatting/ReferenceUnitTest.php b/test/Sniffs/Formatting/ReferenceUnitTest.php index a4909f87..07bd069d 100644 --- a/test/Sniffs/Formatting/ReferenceUnitTest.php +++ b/test/Sniffs/Formatting/ReferenceUnitTest.php @@ -8,11 +8,7 @@ class ReferenceUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 3 => 1, @@ -24,11 +20,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Formatting/ReturnTypeUnitTest.php b/test/Sniffs/Formatting/ReturnTypeUnitTest.php index 9fd94b9d..ed8c49c8 100644 --- a/test/Sniffs/Formatting/ReturnTypeUnitTest.php +++ b/test/Sniffs/Formatting/ReturnTypeUnitTest.php @@ -8,11 +8,7 @@ class ReturnTypeUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { if ($testFile === 'ReturnTypeUnitTest.1.inc') { return [ @@ -67,11 +63,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php index e53391d6..4fc1f99c 100644 --- a/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php +++ b/test/Sniffs/Formatting/UnnecessaryParenthesesUnitTest.php @@ -8,11 +8,7 @@ class UnnecessaryParenthesesUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 7 => 1, @@ -59,11 +55,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Functions/ParamUnitTest.php b/test/Sniffs/Functions/ParamUnitTest.php index f4474eb7..97ea5980 100644 --- a/test/Sniffs/Functions/ParamUnitTest.php +++ b/test/Sniffs/Functions/ParamUnitTest.php @@ -8,11 +8,7 @@ class ParamUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { switch ($testFile) { case 'ParamUnitTest.1.inc': @@ -87,11 +83,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Functions/ReturnTypeUnitTest.php b/test/Sniffs/Functions/ReturnTypeUnitTest.php index 0e7a13bb..8b88268c 100644 --- a/test/Sniffs/Functions/ReturnTypeUnitTest.php +++ b/test/Sniffs/Functions/ReturnTypeUnitTest.php @@ -8,11 +8,7 @@ class ReturnTypeUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { switch ($testFile) { case 'ReturnTypeUnitTest.1.inc': @@ -183,11 +179,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Functions/ThrowsUnitTest.php b/test/Sniffs/Functions/ThrowsUnitTest.php index 5503ac91..d64384c0 100644 --- a/test/Sniffs/Functions/ThrowsUnitTest.php +++ b/test/Sniffs/Functions/ThrowsUnitTest.php @@ -8,11 +8,7 @@ class ThrowsUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 13 => 1, @@ -36,11 +32,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Methods/LineAfterUnitTest.php b/test/Sniffs/Methods/LineAfterUnitTest.php index 4bb0a676..7cec6d2c 100644 --- a/test/Sniffs/Methods/LineAfterUnitTest.php +++ b/test/Sniffs/Methods/LineAfterUnitTest.php @@ -8,11 +8,7 @@ class LineAfterUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { switch ($testFile) { case 'LineAfterUnitTest.1.inc': @@ -55,11 +51,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php index afa480b6..f5844850 100644 --- a/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php +++ b/test/Sniffs/Namespaces/AlphabeticallySortedUsesUnitTest.php @@ -8,11 +8,7 @@ class AlphabeticallySortedUsesUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { switch ($testFile) { case 'AlphabeticallySortedUsesUnitTest.1.inc': @@ -32,11 +28,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.php b/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.php index 9cc8dd75..500ab3c9 100644 --- a/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.php +++ b/test/Sniffs/Namespaces/ConstAndFunctionKeywordsUnitTest.php @@ -8,11 +8,7 @@ class ConstAndFunctionKeywordsUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 3 => 1, @@ -22,11 +18,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.php b/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.php index 1f64ea50..e62fb953 100644 --- a/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.php +++ b/test/Sniffs/Namespaces/UnusedUseStatementUnitTest.php @@ -8,20 +8,12 @@ class UnusedUseStatementUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return []; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return [ 6 => 1, diff --git a/test/Sniffs/Namespaces/UseDoesNotStartWithBackslashUnitTest.php b/test/Sniffs/Namespaces/UseDoesNotStartWithBackslashUnitTest.php index ae4553f7..c5dd7c49 100644 --- a/test/Sniffs/Namespaces/UseDoesNotStartWithBackslashUnitTest.php +++ b/test/Sniffs/Namespaces/UseDoesNotStartWithBackslashUnitTest.php @@ -8,11 +8,7 @@ class UseDoesNotStartWithBackslashUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 4 => 1, @@ -21,11 +17,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/NamingConventions/ValidVariableNameUnitTest.php b/test/Sniffs/NamingConventions/ValidVariableNameUnitTest.php index f4209fa0..9ebde172 100644 --- a/test/Sniffs/NamingConventions/ValidVariableNameUnitTest.php +++ b/test/Sniffs/NamingConventions/ValidVariableNameUnitTest.php @@ -8,11 +8,7 @@ class ValidVariableNameUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 15 => 1, @@ -21,11 +17,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Operators/BooleanOperatorUnitTest.php b/test/Sniffs/Operators/BooleanOperatorUnitTest.php index 9a388ee5..89a77b26 100644 --- a/test/Sniffs/Operators/BooleanOperatorUnitTest.php +++ b/test/Sniffs/Operators/BooleanOperatorUnitTest.php @@ -8,11 +8,7 @@ class BooleanOperatorUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 3 => 1, @@ -26,11 +22,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Operators/TernaryOperatorUnitTest.php b/test/Sniffs/Operators/TernaryOperatorUnitTest.php index c4a9b4b5..c0247fc3 100644 --- a/test/Sniffs/Operators/TernaryOperatorUnitTest.php +++ b/test/Sniffs/Operators/TernaryOperatorUnitTest.php @@ -8,11 +8,7 @@ class TernaryOperatorUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 3 => 1, @@ -28,11 +24,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php index 68abb39a..d9672439 100644 --- a/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php +++ b/test/Sniffs/PHP/CorrectClassNameCaseUnitTest.php @@ -8,11 +8,7 @@ class CorrectClassNameCaseUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { switch ($testFile) { case 'CorrectClassNameCaseUnitTest.1.inc': @@ -61,11 +57,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.php b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.php index 979680f5..26a79dec 100644 --- a/test/Sniffs/PHP/DeclareStrictTypesUnitTest.php +++ b/test/Sniffs/PHP/DeclareStrictTypesUnitTest.php @@ -8,11 +8,7 @@ class DeclareStrictTypesUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { switch ($testFile) { case 'DeclareStrictTypesUnitTest.1.inc': @@ -58,11 +54,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/PHP/ImportInternalConstantUnitTest.php b/test/Sniffs/PHP/ImportInternalConstantUnitTest.php index d9aa2e16..669a0e98 100644 --- a/test/Sniffs/PHP/ImportInternalConstantUnitTest.php +++ b/test/Sniffs/PHP/ImportInternalConstantUnitTest.php @@ -8,11 +8,7 @@ class ImportInternalConstantUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { switch ($testFile) { case 'ImportInternalConstantUnitTest.1.inc': @@ -48,11 +44,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/PHP/ImportInternalFunctionUnitTest.php b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.php index cc646050..59470a88 100644 --- a/test/Sniffs/PHP/ImportInternalFunctionUnitTest.php +++ b/test/Sniffs/PHP/ImportInternalFunctionUnitTest.php @@ -8,11 +8,7 @@ class ImportInternalFunctionUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { switch ($testFile) { case 'ImportInternalFunctionUnitTest.1.inc': @@ -63,11 +59,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.php b/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.php index fa32450a..d7df5dfa 100644 --- a/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.php +++ b/test/Sniffs/PHP/InstantiatingParenthesisUnitTest.php @@ -8,11 +8,7 @@ class InstantiatingParenthesisUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 3 => 1, @@ -34,11 +30,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/PHP/RedundantSemicolonUnitTest.php b/test/Sniffs/PHP/RedundantSemicolonUnitTest.php index 1f55eea4..b662d94d 100644 --- a/test/Sniffs/PHP/RedundantSemicolonUnitTest.php +++ b/test/Sniffs/PHP/RedundantSemicolonUnitTest.php @@ -8,11 +8,7 @@ class RedundantSemicolonUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 4 => 1, @@ -22,11 +18,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/PHP/SingleSemicolonUnitTest.php b/test/Sniffs/PHP/SingleSemicolonUnitTest.php index c4a19f2c..10fd3412 100644 --- a/test/Sniffs/PHP/SingleSemicolonUnitTest.php +++ b/test/Sniffs/PHP/SingleSemicolonUnitTest.php @@ -8,11 +8,7 @@ class SingleSemicolonUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 3 => 1, @@ -20,11 +16,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/PHP/TypeCastingUnitTest.php b/test/Sniffs/PHP/TypeCastingUnitTest.php index 4c7fb82b..4b3159d7 100644 --- a/test/Sniffs/PHP/TypeCastingUnitTest.php +++ b/test/Sniffs/PHP/TypeCastingUnitTest.php @@ -8,11 +8,7 @@ class TypeCastingUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 3 => 1, @@ -47,11 +43,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/Strings/NoConcatenationAtTheEndUnitTest.php b/test/Sniffs/Strings/NoConcatenationAtTheEndUnitTest.php index 77141d79..39bffa78 100644 --- a/test/Sniffs/Strings/NoConcatenationAtTheEndUnitTest.php +++ b/test/Sniffs/Strings/NoConcatenationAtTheEndUnitTest.php @@ -8,11 +8,7 @@ class NoConcatenationAtTheEndUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 3 => 1, @@ -20,11 +16,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/TestCase.php b/test/Sniffs/TestCase.php index 47619a0f..ff18c68b 100644 --- a/test/Sniffs/TestCase.php +++ b/test/Sniffs/TestCase.php @@ -63,7 +63,7 @@ protected function setUp() * @param string $testFileBase The base path that the unit tests files will have. * @return string[] */ - protected function getTestFiles($testFileBase) + protected function getTestFiles($testFileBase) : array { $testFiles = []; @@ -89,10 +89,8 @@ protected function getTestFiles($testFileBase) /** * Should this test be skipped for some reason. - * - * @return false */ - protected function shouldSkipTest() + protected function shouldSkipTest() : bool { return false; } @@ -100,7 +98,7 @@ protected function shouldSkipTest() /** * Tests the extending classes Sniff class. */ - final public function testSniff() + final public function testSniff() : void { // Skip this test if we can't run in this environment. if ($this->shouldSkipTest()) { @@ -109,7 +107,7 @@ final public function testSniff() $sniffCode = Common::getSniffCode(get_class($this)); $sniffCode = str_replace('Test.', '.', $sniffCode); - list($standardName, $categoryName, $sniffName) = explode('.', $sniffCode); + [$standardName, $categoryName, $sniffName] = explode('.', $sniffCode); $testFileBase = $this->testsDir . $categoryName . DIRECTORY_SEPARATOR . $sniffName . 'UnitTest.'; @@ -182,7 +180,7 @@ final public function testSniff() * @return string[] * @throws RuntimeException */ - public function generateFailureMessages(LocalFile $file) + private function generateFailureMessages(LocalFile $file) : array { $testFile = $file->getFilename(); @@ -367,7 +365,7 @@ public function generateFailureMessages(LocalFile $file) * @param Config $config The config data for the run. * @return string[] */ - public function setCliValues($filename, Config $config) + public function setCliValues(string $filename, Config $config) : array { return []; } @@ -380,7 +378,7 @@ public function setCliValues($filename, Config $config) * * @return int[] */ - abstract protected function getErrorList(); + abstract protected function getErrorList(string $testFile = '') : array; /** * Returns the lines where warnings should occur. @@ -390,5 +388,5 @@ abstract protected function getErrorList(); * * @return int[] */ - abstract protected function getWarningList(); + abstract protected function getWarningList(string $testFile = '') : array; } diff --git a/test/Sniffs/WhiteSpace/BlankLineUnitTest.php b/test/Sniffs/WhiteSpace/BlankLineUnitTest.php index bc682484..a766a343 100644 --- a/test/Sniffs/WhiteSpace/BlankLineUnitTest.php +++ b/test/Sniffs/WhiteSpace/BlankLineUnitTest.php @@ -8,11 +8,7 @@ class BlankLineUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 2 => 1, @@ -24,11 +20,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.php b/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.php index f113824a..dbb8fa13 100644 --- a/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.php +++ b/test/Sniffs/WhiteSpace/CommaSpacingUnitTest.php @@ -8,11 +8,7 @@ class CommaSpacingUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 3 => 1, @@ -33,11 +29,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/WhiteSpace/NoBlankLineAtStartUnitTest.php b/test/Sniffs/WhiteSpace/NoBlankLineAtStartUnitTest.php index c84aed42..611fd7fb 100644 --- a/test/Sniffs/WhiteSpace/NoBlankLineAtStartUnitTest.php +++ b/test/Sniffs/WhiteSpace/NoBlankLineAtStartUnitTest.php @@ -8,11 +8,7 @@ class NoBlankLineAtStartUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { return [ 3 => 1, @@ -28,11 +24,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php index da6dacaa..a0d8bb0d 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.php @@ -8,11 +8,7 @@ class ScopeIndentUnitTest extends TestCase { - /** - * @param string $testFile - * @return int[] - */ - public function getErrorList($testFile = '') + public function getErrorList(string $testFile = '') : array { if ($testFile === 'ScopeIndentUnitTest.1.inc') { return [ @@ -260,11 +256,7 @@ public function getErrorList($testFile = '') ]; } - /** - * @param string $testFile - * @return int[] - */ - public function getWarningList($testFile = '') + public function getWarningList(string $testFile = '') : array { return []; } From e9b9b9efc804eba7f4124ee1f3b7ac57a40d5929 Mon Sep 17 00:00:00 2001 From: webimpress Date: Tue, 27 Mar 2018 15:14:27 +0100 Subject: [PATCH 206/225] Updated PHPUnit configuration to not report risky tests --- phpunit.xml.dist | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 56d8195e..91d7dc3c 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,5 +1,9 @@ - + ./test From 4a137cf7ee39425bd375e37998d64f04776bf15e Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Mar 2018 09:00:07 +0100 Subject: [PATCH 207/225] Added new sniff Files.DeclareStrictTypes Checks if strict type declaration is below comment with license, copyright and see tags. --- .../Sniffs/Arrays/TrailingArrayCommaSniff.php | 8 +- .../Sniffs/Files/DeclareStrictTypesSniff.php | 125 ++++++++++++++++++ .../Namespaces/UnusedUseStatementSniff.php | 18 ++- .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 26 ++-- .../Files/DeclareStrictTypesUnitTest.1.inc | 9 ++ .../Files/DeclareStrictTypesUnitTest.2.inc | 12 ++ .../DeclareStrictTypesUnitTest.2.inc.fixed | 14 ++ .../Files/DeclareStrictTypesUnitTest.3.inc | 13 ++ .../DeclareStrictTypesUnitTest.3.inc.fixed | 15 +++ .../Files/DeclareStrictTypesUnitTest.4.inc | 13 ++ .../DeclareStrictTypesUnitTest.4.inc.fixed | 15 +++ .../Files/DeclareStrictTypesUnitTest.5.inc | 14 ++ .../DeclareStrictTypesUnitTest.5.inc.fixed | 16 +++ .../Files/DeclareStrictTypesUnitTest.inc | 4 + .../Files/DeclareStrictTypesUnitTest.php | 31 +++++ 15 files changed, 306 insertions(+), 27 deletions(-) create mode 100644 src/ZendCodingStandard/Sniffs/Files/DeclareStrictTypesSniff.php create mode 100644 test/Sniffs/Files/DeclareStrictTypesUnitTest.1.inc create mode 100644 test/Sniffs/Files/DeclareStrictTypesUnitTest.2.inc create mode 100644 test/Sniffs/Files/DeclareStrictTypesUnitTest.2.inc.fixed create mode 100644 test/Sniffs/Files/DeclareStrictTypesUnitTest.3.inc create mode 100644 test/Sniffs/Files/DeclareStrictTypesUnitTest.3.inc.fixed create mode 100644 test/Sniffs/Files/DeclareStrictTypesUnitTest.4.inc create mode 100644 test/Sniffs/Files/DeclareStrictTypesUnitTest.4.inc.fixed create mode 100644 test/Sniffs/Files/DeclareStrictTypesUnitTest.5.inc create mode 100644 test/Sniffs/Files/DeclareStrictTypesUnitTest.5.inc.fixed create mode 100644 test/Sniffs/Files/DeclareStrictTypesUnitTest.inc create mode 100644 test/Sniffs/Files/DeclareStrictTypesUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php index 21fb599d..0e2c35ef 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php @@ -1,8 +1,4 @@ getTokens(); + + $string = $phpcsFile->findNext( + T_STRING, + $tokens[$stackPtr]['parenthesis_opener'] + 1, + $tokens[$stackPtr]['parenthesis_closer'] + ); + + // It is no strict type declaration. + if ($string === false + || stripos($tokens[$string]['content'], 'strict_types') === false + ) { + return; + } + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); + + if ($tokens[$prev]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + if ($this->checkTags($phpcsFile, $tokens[$tokens[$prev]['comment_opener']])) { + return; + } + } + + $eos = $phpcsFile->findEndOfStatement($stackPtr); + + if ($tokens[$prev]['code'] !== T_OPEN_TAG) { + $error = 'Wrong place of strict type declaration statement; must be above comment'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'BelowComment'); + + if ($fix) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $prev - 1, null, true); + $this->fix($phpcsFile, $stackPtr, $eos, $prev); + } + + return; + } + + $next = $phpcsFile->findNext(T_WHITESPACE, $eos + 1, null, true); + if ($tokens[$next]['code'] === T_DOC_COMMENT_OPEN_TAG + && $this->checkTags($phpcsFile, $tokens[$next]) + ) { + $error = 'Wrong place of strict type declaration statement; must be below comment'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'AboveComment'); + + if ($fix) { + $this->fix($phpcsFile, $stackPtr, $eos, $tokens[$next]['comment_closer']); + } + } + } + + private function fix(File $phpcsFile, int $start, int $eos, int $after) : void + { + $declaration = $phpcsFile->getTokensAsString($start, $eos - $start + 1); + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($after, $phpcsFile->eolChar . $declaration . $phpcsFile->eolChar); + for ($i = $start; $i <= $eos; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->endChangeset(); + } + + private function checkTags(File $phpcsFile, array $tag) : bool + { + $tokens = $phpcsFile->getTokens(); + + $tags = array_map(function ($value) { + return strtolower($value); + }, $this->containsTags); + + foreach ($tag['comment_tags'] ?? [] as $token) { + if (false !== ($i = array_search(strtolower($tokens[$token]['content']), $tags, true))) { + unset($tags[$i]); + } + } + + return ! $tags; + } +} diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index 349a4135..e0270a0f 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -1,14 +1,4 @@ 1]; + case 'DeclareStrictTypesUnitTest.3.inc': + return [7 => 1]; + case 'DeclareStrictTypesUnitTest.4.inc': + return [7 => 1]; + case 'DeclareStrictTypesUnitTest.5.inc': + return [8 => 1]; + } + + return []; + } + + public function getWarningList(string $testFile = '') : array + { + return []; + } +} From 09c34a11025bceda0f8402c8d5d9418b52b2c03a Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Mar 2018 09:42:32 +0100 Subject: [PATCH 208/225] TrailingArrayCommaSniff improvements Extends AbstractArraySniff and process single and multiline arrays. There must be a trailing comma after the last element in multiline arrays and must not in single-line arrays. --- .../Sniffs/Arrays/TrailingArrayCommaSniff.php | 94 ++++++++----------- .../Arrays/TrailingArrayCommaUnitTest.inc | 3 + .../TrailingArrayCommaUnitTest.inc.fixed | 3 + .../Arrays/TrailingArrayCommaUnitTest.php | 2 + 4 files changed, 47 insertions(+), 55 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php index 0e2c35ef..269fbe9b 100644 --- a/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php +++ b/src/ZendCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php @@ -5,77 +5,61 @@ namespace ZendCodingStandard\Sniffs\Arrays; use PHP_CodeSniffer\Files\File; -use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Sniffs\AbstractArraySniff; +use PHP_CodeSniffer\Util\Tokens; use const T_COMMA; -use const T_COMMENT; -use const T_DOC_COMMENT; -use const T_DOC_COMMENT_CLOSE_TAG; -use const T_DOC_COMMENT_OPEN_TAG; -use const T_DOC_COMMENT_STAR; -use const T_DOC_COMMENT_STRING; -use const T_DOC_COMMENT_TAG; -use const T_DOC_COMMENT_WHITESPACE; -use const T_OPEN_SHORT_ARRAY; -use const T_WHITESPACE; -/** - * Copied from SlevomatCodingStandard\Sniffs\Arrays\TrailingArrayCommaSniff - * with fix: comma shouldn't be added after "[" for empty arrays "[]". - */ -class TrailingArrayCommaSniff implements Sniff +class TrailingArrayCommaSniff extends AbstractArraySniff { /** - * @return int[] + * Processes a single-line array definition. + * + * @param File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. */ - public function register() : array + protected function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) : void { - return [T_OPEN_SHORT_ARRAY]; + $tokens = $phpcsFile->getTokens(); + $beforeClose = $phpcsFile->findPrevious(Tokens::$emptyTokens, $arrayEnd - 1, $arrayStart + 1, true); + + if ($beforeClose && $tokens[$beforeClose]['code'] === T_COMMA) { + $error = 'Single-line arrays must not have a trailing comma after the last element'; + $fix = $phpcsFile->addFixableError($error, $beforeClose, 'AdditionalTrailingComma'); + + if ($fix) { + $phpcsFile->fixer->replaceToken($beforeClose, ''); + } + } } /** - * @param int $stackPtr + * Processes a multi-line array definition. + * + * @param File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. */ - public function process(File $phpcsFile, $stackPtr) + protected function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) : void { $tokens = $phpcsFile->getTokens(); - $arrayToken = $tokens[$stackPtr]; - $closeParenthesisPointer = $arrayToken['bracket_closer']; - $openParenthesisToken = $tokens[$arrayToken['bracket_opener']]; - $closeParenthesisToken = $tokens[$closeParenthesisPointer]; - - if ($openParenthesisToken['line'] === $closeParenthesisToken['line']) { - return; - } - - $previousToCloseParenthesisPointer = $phpcsFile->findPrevious( - [ - T_WHITESPACE, - T_COMMENT, - T_DOC_COMMENT, - T_DOC_COMMENT_OPEN_TAG, - T_DOC_COMMENT_CLOSE_TAG, - T_DOC_COMMENT_STAR, - T_DOC_COMMENT_STRING, - T_DOC_COMMENT_TAG, - T_DOC_COMMENT_WHITESPACE, - ], - $closeParenthesisPointer - 1, - null, - true - ); - - $previousToCloseParenthesisToken = $tokens[$previousToCloseParenthesisPointer]; + $beforeClose = $phpcsFile->findPrevious(Tokens::$emptyTokens, $arrayEnd - 1, $arrayStart + 1, true); - if ($previousToCloseParenthesisToken['code'] !== T_COMMA - && $previousToCloseParenthesisToken['code'] !== T_OPEN_SHORT_ARRAY - && $closeParenthesisToken['line'] !== $previousToCloseParenthesisToken['line'] - ) { - $error = 'Multiline arrays must have a trailing comma after the last element'; - $fix = $phpcsFile->addFixableError($error, $previousToCloseParenthesisPointer, 'TrailingComma'); + if ($beforeClose && $tokens[$beforeClose]['code'] !== T_COMMA) { + $error = 'Multi-line arrays must have a trailing comma after the last element'; + $fix = $phpcsFile->addFixableError($error, $beforeClose, 'MissingTrailingComma'); if ($fix) { - $phpcsFile->fixer->addContent($previousToCloseParenthesisPointer, ','); + $phpcsFile->fixer->addContent($beforeClose, ','); } } } diff --git a/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.inc b/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.inc index eb8f17c6..719c5769 100644 --- a/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.inc +++ b/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.inc @@ -21,3 +21,6 @@ $a7 = [ ['a2'], ['a3'] ]; + +$s = ['a',/**/]; +$s1 = ['a' => 'b', ]; diff --git a/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.inc.fixed b/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.inc.fixed index 20480cb6..ef3a8a6b 100644 --- a/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.inc.fixed +++ b/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.inc.fixed @@ -21,3 +21,6 @@ $a7 = [ ['a2'], ['a3'], ]; + +$s = ['a'/**/]; +$s1 = ['a' => 'b' ]; diff --git a/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.php b/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.php index bcbb5b1a..064a88ae 100644 --- a/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.php +++ b/test/Sniffs/Arrays/TrailingArrayCommaUnitTest.php @@ -15,6 +15,8 @@ public function getErrorList(string $testFile = '') : array 14 => 1, 17 => 1, 22 => 1, + 25 => 1, + 26 => 1, ]; } From ed58b09fb96abe9c4d7820dfdd5718f45f043675 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Mar 2018 10:58:35 +0100 Subject: [PATCH 209/225] Do not include removed use statements when processing fixed file In case the use statement was removed previously we shouldn't have it on the list of imported class/function/constant as it can't be used later on. --- src/ZendCodingStandard/Helper/Namespaces.php | 13 +++++++++++++ .../Sniffs/Namespaces/UnusedUseStatementSniff.php | 2 ++ 2 files changed, 15 insertions(+) diff --git a/src/ZendCodingStandard/Helper/Namespaces.php b/src/ZendCodingStandard/Helper/Namespaces.php index e21072d7..43b5a8ec 100644 --- a/src/ZendCodingStandard/Helper/Namespaces.php +++ b/src/ZendCodingStandard/Helper/Namespaces.php @@ -7,6 +7,7 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Util\Tokens; use ZendCodingStandard\CodingStandard; +use ZendCodingStandard\Sniffs\Namespaces\UnusedUseStatementSniff; use function in_array; use function ltrim; @@ -65,6 +66,10 @@ private function getGlobalUses(File $phpcsFile, int $stackPtr = 0) : array continue; } + if (isset($phpcsFile->getMetrics()[UnusedUseStatementSniff::class]['values'][$use])) { + continue; + } + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, $use + 1, null, true); if ($tokens[$nextToken]['code'] === T_STRING @@ -158,6 +163,10 @@ private function getImportedConstants(File $phpcsFile, int $stackPtr, ?int &$las continue; } + if (isset($phpcsFile->getMetrics()[UnusedUseStatementSniff::class]['values'][$use])) { + continue; + } + if ($next = $this->isConstUse($phpcsFile, $use)) { $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); $end = $phpcsFile->findPrevious( @@ -205,6 +214,10 @@ private function getImportedFunctions(File $phpcsFile, int $stackPtr, ?int &$las continue; } + if (isset($phpcsFile->getMetrics()[UnusedUseStatementSniff::class]['values'][$use])) { + continue; + } + if ($next = $this->isFunctionUse($phpcsFile, $use)) { $start = $phpcsFile->findNext([T_STRING, T_NS_SEPARATOR], $next + 1); $end = $phpcsFile->findPrevious( diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php index e0270a0f..7e35581c 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/UnusedUseStatementSniff.php @@ -208,6 +208,8 @@ public function process(File $phpcsFile, $stackPtr) } $phpcsFile->fixer->endChangeset(); + + $phpcsFile->recordMetric($stackPtr, __CLASS__, $stackPtr); } } } From 55ed5743b63cfa96c6761374bcf79d76c1d13d49 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Mar 2018 11:11:18 +0100 Subject: [PATCH 210/225] Updated doc comments --- src/ZendCodingStandard/Helper/Namespaces.php | 23 +++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/ZendCodingStandard/Helper/Namespaces.php b/src/ZendCodingStandard/Helper/Namespaces.php index 43b5a8ec..077de4b2 100644 --- a/src/ZendCodingStandard/Helper/Namespaces.php +++ b/src/ZendCodingStandard/Helper/Namespaces.php @@ -41,9 +41,12 @@ private function getNamespace(File $phpcsFile, int $stackPtr) : string } /** - * Returns array of imported classes. Key is lowercase name, and value is FQCN. - * - * @return string[][] + * @return array Array of imported classes { + * @var array $_ Key is lowercase class alias name { + * @var string $alias Original class alias name + * @var string $class FQCN + * } + * } */ private function getGlobalUses(File $phpcsFile, int $stackPtr = 0) : array { @@ -139,7 +142,12 @@ private function isConstUse(File $phpcsFile, int $stackPtr) } /** - * @return string[][] + * @return array Array of imported constants { + * @var array $_ Key is lowercase constant name { + * @var string $name Original constant name + * @var string $fqn Fully qualified constant name without leading slashes + * } + * } */ private function getImportedConstants(File $phpcsFile, int $stackPtr, ?int &$lastUse) : array { @@ -190,7 +198,12 @@ private function getImportedConstants(File $phpcsFile, int $stackPtr, ?int &$las } /** - * @return string[][] + * @return array Array of imported functions { + * @var array $_ Key is lowercase function name { + * @var string $name Original function name + * @var string $fqn Fully qualified function name without leading slashes + * } + * } */ private function getImportedFunctions(File $phpcsFile, int $stackPtr, ?int &$lastUse) : array { From 21dc5d75b059ab7be682d0d912c4eb1a18a0c75e Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Mar 2018 13:49:39 +0100 Subject: [PATCH 211/225] Return numTags+1 to not run this sniff anymore in the file --- .../Sniffs/PHP/DeclareStrictTypesSniff.php | 6 +++--- .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/PHP/DeclareStrictTypesSniff.php b/src/ZendCodingStandard/Sniffs/PHP/DeclareStrictTypesSniff.php index 9e153954..48dea4e9 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/DeclareStrictTypesSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/DeclareStrictTypesSniff.php @@ -92,7 +92,7 @@ public function process(File $phpcsFile, $stackPtr) $this->checkOtherDeclarations($phpcsFile); - return $phpcsFile->numTokens; + return $phpcsFile->numTokens + 1; } $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); @@ -309,7 +309,7 @@ public function process(File $phpcsFile, $stackPtr) $this->checkOtherDeclarations($phpcsFile, $next); - return $phpcsFile->numTokens; + return $phpcsFile->numTokens + 1; } } @@ -322,7 +322,7 @@ public function process(File $phpcsFile, $stackPtr) $phpcsFile->fixer->addContent($stackPtr, $this->format . $phpcsFile->eolChar); } - return $phpcsFile->numTokens; + return $phpcsFile->numTokens + 1; } /** diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index f6fc2b97..81057366 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -248,7 +248,7 @@ public function process(File $phpcsFile, $stackPtr) if ($tokens[$i]['code'] === T_OPEN_TAG) { // $error = 'This sniff does not support files with multiple PHP open tags.'; // $phpcsFile->addError($error, $i, 'UnsupportedFile'); - // return $phpcsFile->numTokens; + // return $phpcsFile->numTokens + 1; // if ($depth === 0) { $extraIndent = max($tokens[$i]['column'] - 1 - ($depth * $this->indent), 0); $extraIndent = (int) (ceil($extraIndent / $this->indent) * $this->indent); @@ -763,7 +763,7 @@ public function process(File $phpcsFile, $stackPtr) } } - return $phpcsFile->numTokens; + return $phpcsFile->numTokens + 1; } /** From d6f429219d67ac7a6aa9f4f83883831f0c4e5935 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Mar 2018 14:30:59 +0100 Subject: [PATCH 212/225] Use phpcs: annotations instead of @codingStandards* --- test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc | 12 ++++++------ .../Sniffs/Formatting/ReturnTypeUnitTest.1.inc.fixed | 12 ++++++------ test/Sniffs/Formatting/ReturnTypeUnitTest.inc | 6 +++--- test/Sniffs/Formatting/ReturnTypeUnitTest.inc.fixed | 6 +++--- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc b/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc index 2ab6872a..1880e09e 100644 --- a/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc +++ b/test/Sniffs/Formatting/ReturnTypeUnitTest.1.inc @@ -1,7 +1,7 @@ Date: Wed, 28 Mar 2018 14:31:25 +0100 Subject: [PATCH 213/225] Added phpcs.xsd schema in XML ruleset definitions --- README.md | 4 +++- phpcs.xml | 4 +++- src/ZendCodingStandard/ruleset.xml | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5236b5d6..42235de7 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,9 @@ Repository with all coding standard ruleset for Zend Framework repositories. ```xml - + diff --git a/phpcs.xml b/phpcs.xml index f7d0b9fa..13388786 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -1,5 +1,7 @@ - + src diff --git a/src/ZendCodingStandard/ruleset.xml b/src/ZendCodingStandard/ruleset.xml index 09c05d46..897ee39d 100755 --- a/src/ZendCodingStandard/ruleset.xml +++ b/src/ZendCodingStandard/ruleset.xml @@ -1,5 +1,7 @@ - + Zend Framework Coding Standard From 1db8b64cadaff1a6ffd9dd677504cbd026d5fec5 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Mar 2018 14:43:18 +0100 Subject: [PATCH 214/225] Added PEAR.Commenting.InlineComment to disallow hash (#) comments --- src/ZendCodingStandard/ruleset.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ZendCodingStandard/ruleset.xml b/src/ZendCodingStandard/ruleset.xml index 897ee39d..87771e2e 100755 --- a/src/ZendCodingStandard/ruleset.xml +++ b/src/ZendCodingStandard/ruleset.xml @@ -43,6 +43,9 @@ + + + From bec92d7892090e2bdacc426bf8efc49956d2ad66 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Mar 2018 14:45:26 +0100 Subject: [PATCH 215/225] Added phpcs and @codingStandards* sniffs @codingStandards* tags are deprecated since PHP_CodeSniffer 3.2.0 We want to use only @phpcs: notation. We can't automatically change it in files which are whole ignored, and it should be changed there manually. --- .../Commenting/CodingStandardTagsSniff.php | 126 ++++++++++++++++++ .../Commenting/PhpcsAnnotationSniff.php | 66 +++++++++ .../Commenting/CodingStandardTagsUnitTest.inc | 40 ++++++ .../CodingStandardTagsUnitTest.inc.fixed | 40 ++++++ .../Commenting/CodingStandardTagsUnitTest.php | 41 ++++++ .../Commenting/PhpcsAnnotationUnitTest.inc | 40 ++++++ .../PhpcsAnnotationUnitTest.inc.fixed | 40 ++++++ .../Commenting/PhpcsAnnotationUnitTest.php | 41 ++++++ 8 files changed, 434 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/Commenting/CodingStandardTagsSniff.php create mode 100644 src/ZendCodingStandard/Sniffs/Commenting/PhpcsAnnotationSniff.php create mode 100644 test/Sniffs/Commenting/CodingStandardTagsUnitTest.inc create mode 100644 test/Sniffs/Commenting/CodingStandardTagsUnitTest.inc.fixed create mode 100644 test/Sniffs/Commenting/CodingStandardTagsUnitTest.php create mode 100644 test/Sniffs/Commenting/PhpcsAnnotationUnitTest.inc create mode 100644 test/Sniffs/Commenting/PhpcsAnnotationUnitTest.inc.fixed create mode 100644 test/Sniffs/Commenting/PhpcsAnnotationUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Commenting/CodingStandardTagsSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/CodingStandardTagsSniff.php new file mode 100644 index 00000000..dec28c8c --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Commenting/CodingStandardTagsSniff.php @@ -0,0 +1,126 @@ + '@phpcs:ignoreFile', + '@codingStandardsIgnoreStart' => '@phpcs:disable', + '@codingStandardsIgnoreEnd' => '@phpcs:enable', + '@codingStandardsIgnoreLine' => '@phpcs:ignore', + '@codingStandardsChangeSetting' => '@phpcs:set', + ]; + + /** + * @return int[] + */ + public function register() : array + { + return [T_OPEN_TAG]; + } + + /** + * @param int $stackPtr + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $ignoredLines = $phpcsFile->tokenizer->ignoredLines; + $phpcsFile->tokenizer->ignoredLines = []; + + $next = $stackPtr; + while ($next = $phpcsFile->findNext([T_COMMENT, T_DOC_COMMENT_TAG], $next + 1)) { + if ($tokens[$next]['code'] === T_DOC_COMMENT_TAG) { + $lower = strtolower($tokens[$next]['content']); + if ($tag = key(array_filter($this->replacements, function ($key) use ($lower) { + return strtolower($key) === $lower; + }, ARRAY_FILTER_USE_KEY))) { + $this->overrideToken($phpcsFile, $next); + + $error = 'PHP_CodeSniffer tag %s in line %d is deprecated; use %s instead'; + $data = [ + $tag, + $tokens[$next]['line'], + $this->replacements[$tag], + ]; + $fix = $phpcsFile->addFixableError($error, $next, 'DeprecatedTag', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($next, $this->replacements[$tag]); + } + } + + continue; + } + + $content = ltrim($tokens[$next]['content'], ' /*'); + foreach ($this->replacements as $old => $new) { + if (stripos($content, $old) !== false) { + $this->overrideToken($phpcsFile, $next); + + $error = 'PHP_CodeSniffer tag %s in line is deprecated; use %s instead'; + $data = [ + $old, + $tokens[$next]['line'], + $new, + ]; + $fix = $phpcsFile->addFixableError($error, $next, 'DeprecatedTag', $data); + + if ($fix) { + $content = preg_replace( + '/' . preg_quote($old, '/') . '/i', + $new, + $tokens[$next]['content'] + ); + $phpcsFile->fixer->replaceToken($next, $content); + } + break; + } + } + } + + $phpcsFile->tokenizer->ignoredLines = $ignoredLines; + return $phpcsFile->numTokens + 1; + } + + private function overrideToken(File $phpcsFile, int $stackPtr) + { + $clear = function () use ($stackPtr) { + $this->tokens[$stackPtr]['content'] = 'ZF-CS'; + }; + + $clear->bindTo($phpcsFile, File::class)(); + } +} diff --git a/src/ZendCodingStandard/Sniffs/Commenting/PhpcsAnnotationSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/PhpcsAnnotationSniff.php new file mode 100644 index 00000000..19acc52a --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Commenting/PhpcsAnnotationSniff.php @@ -0,0 +1,66 @@ +getTokens(); + $ignoredLines = $phpcsFile->tokenizer->ignoredLines; + $phpcsFile->tokenizer->ignoredLines = []; + + $next = $stackPtr; + while ($next = $phpcsFile->findNext(Tokens::$phpcsCommentTokens, $next + 1)) { + $this->overrideToken($phpcsFile, $next); + + if ($tokens[$next - 1]['content'] !== '@' + && ! preg_match('/@phpcs:/i', $tokens[$next]['content']) + ) { + $error = 'Missing @ before phpcs annotation'; + $fix = $phpcsFile->addFixableError($error, $next, 'MissingAt'); + + if ($fix) { + $content = preg_replace('/phpcs:/i', '@\\0', $tokens[$next]['content']); + $phpcsFile->fixer->replaceToken($next, $content); + } + } + } + + $phpcsFile->tokenizer->ignoredLines = $ignoredLines; + + return $phpcsFile->numTokens + 1; + } + + private function overrideToken(File $phpcsFile, int $stackPtr) + { + $clear = function () use ($stackPtr) { + $this->tokens[$stackPtr]['content'] = 'ZF-CS'; + }; + + $clear->bindTo($phpcsFile, File::class)(); + } +} diff --git a/test/Sniffs/Commenting/CodingStandardTagsUnitTest.inc b/test/Sniffs/Commenting/CodingStandardTagsUnitTest.inc new file mode 100644 index 00000000..906a8b1f --- /dev/null +++ b/test/Sniffs/Commenting/CodingStandardTagsUnitTest.inc @@ -0,0 +1,40 @@ + 1, + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 11 => 1, + 15 => 1, + 19 => 1, + 23 => 1, + 27 => 1, + 30 => 1, + 31 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 36 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 40 => 1, + ]; + } + + public function getWarningList(string $testFile = '') : array + { + return []; + } +} diff --git a/test/Sniffs/Commenting/PhpcsAnnotationUnitTest.inc b/test/Sniffs/Commenting/PhpcsAnnotationUnitTest.inc new file mode 100644 index 00000000..3b9ca9af --- /dev/null +++ b/test/Sniffs/Commenting/PhpcsAnnotationUnitTest.inc @@ -0,0 +1,40 @@ + 1, + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 11 => 1, + 15 => 1, + 19 => 1, + 23 => 1, + 27 => 1, + 30 => 1, + 31 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 36 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 40 => 1, + ]; + } + + public function getWarningList(string $testFile = '') : array + { + return []; + } +} From 14a9253ab4788cfdd00e44bd19892ab765f91f4f Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 28 Mar 2018 15:45:44 +0100 Subject: [PATCH 216/225] Added Array.DoubleArrow sniff to check spacing around double arrow One space is required before and the => cannot be at the end of the line --- src/ZendCodingStandard/Helper/Namespaces.php | 4 +- .../Sniffs/Arrays/DoubleArrowSniff.php | 105 ++++++++++++++++++ .../AlphabeticallySortedTraitsSniff.php | 2 +- .../Sniffs/Classes/TraitUsageSniff.php | 4 +- .../Commenting/FunctionCommentSniff.php | 4 +- .../UnnecessaryParenthesesSniff.php | 6 +- .../AlphabeticallySortedUsesSniff.php | 4 +- .../ValidVariableNameSniff.php | 14 +-- .../PHP/ImportInternalConstantSniff.php | 2 +- .../PHP/ImportInternalFunctionSniff.php | 2 +- .../Sniffs/PHP/TypeCastingSniff.php | 4 +- test/Sniffs/Arrays/DoubleArrowUnitTest.inc | 10 ++ .../Arrays/DoubleArrowUnitTest.inc.fixed | 10 ++ test/Sniffs/Arrays/DoubleArrowUnitTest.php | 24 ++++ test/Sniffs/TestCase.php | 24 ++-- 15 files changed, 184 insertions(+), 35 deletions(-) create mode 100644 src/ZendCodingStandard/Sniffs/Arrays/DoubleArrowSniff.php create mode 100644 test/Sniffs/Arrays/DoubleArrowUnitTest.inc create mode 100644 test/Sniffs/Arrays/DoubleArrowUnitTest.inc.fixed create mode 100644 test/Sniffs/Arrays/DoubleArrowUnitTest.php diff --git a/src/ZendCodingStandard/Helper/Namespaces.php b/src/ZendCodingStandard/Helper/Namespaces.php index 077de4b2..52636f4c 100644 --- a/src/ZendCodingStandard/Helper/Namespaces.php +++ b/src/ZendCodingStandard/Helper/Namespaces.php @@ -187,7 +187,7 @@ private function getImportedConstants(File $phpcsFile, int $stackPtr, ?int &$las $constants[strtoupper($tokens[$name]['content'])] = [ 'name' => $tokens[$name]['content'], - 'fqn' => ltrim($fullName, '\\'), + 'fqn' => ltrim($fullName, '\\'), ]; } @@ -243,7 +243,7 @@ private function getImportedFunctions(File $phpcsFile, int $stackPtr, ?int &$las $functions[strtolower($tokens[$name]['content'])] = [ 'name' => $tokens[$name]['content'], - 'fqn' => ltrim($fullName, '\\'), + 'fqn' => ltrim($fullName, '\\'), ]; } diff --git a/src/ZendCodingStandard/Sniffs/Arrays/DoubleArrowSniff.php b/src/ZendCodingStandard/Sniffs/Arrays/DoubleArrowSniff.php new file mode 100644 index 00000000..9f93c0de --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Arrays/DoubleArrowSniff.php @@ -0,0 +1,105 @@ +checkSpace($phpcsFile, $data); + } + } + + /** + * Processes a multi-line array definition. + * + * @param File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + */ + protected function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) + { + $tokens = $phpcsFile->getTokens(); + + foreach ($indices as $data) { + if (! isset($data['arrow'])) { + continue; + } + + $arrow = $tokens[$data['arrow']]; + $value = $tokens[$data['value_start']]; + + if ($value['line'] > $arrow['line']) { + $error = 'Double arrow in array cannot be at the end of the line'; + $fix = $phpcsFile->addFixableError($error, $data['arrow'], 'AtTheEnd'); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($data['arrow'], ''); + for ($i = $data['arrow'] - 1; $i > $data['index_end']; --$i) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->addContentBefore($data['value_start'], '=> '); + $phpcsFile->fixer->endChangeset(); + } + + continue; + } + + $index = $tokens[$data['index_end']]; + if ($index['line'] === $arrow['line']) { + $this->checkSpace($phpcsFile, $data); + } + } + } + + private function checkSpace(File $phpcsFile, array $element) : void + { + $tokens = $phpcsFile->getTokens(); + + $space = $tokens[$element['arrow'] - 1]; + if ($space['code'] === T_WHITESPACE && $space['content'] !== ' ') { + $error = 'Expected 1 space before "=>"; "%s" found'; + $data = [ + Common::prepareForOutput($space['content']), + ]; + $fix = $phpcsFile->addFixableError($error, $element['arrow'], 'SpaceBefore', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($element['arrow'] - 1, ' '); + } + } + } +} diff --git a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php index ba62254b..f670e2b5 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/AlphabeticallySortedTraitsSniff.php @@ -99,7 +99,7 @@ private function getTraits(File $phpcsFile, int $scopePtr) : array $uses[] = [ 'ptrUse' => $use, - 'name' => trim($phpcsFile->getTokensAsString($use + 1, $endOfName - $use - 1)), + 'name' => trim($phpcsFile->getTokensAsString($use + 1, $endOfName - $use - 1)), 'ptrEnd' => $endOfScope, 'string' => trim($phpcsFile->getTokensAsString($use, $endOfScope - $use + 1)), ]; diff --git a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php index 9394603d..f9ce984a 100644 --- a/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php +++ b/src/ZendCodingStandard/Sniffs/Classes/TraitUsageSniff.php @@ -196,8 +196,8 @@ public function process(File $phpcsFile, $stackPtr) $begin = $phpcsFile->findNext(Tokens::$emptyTokens, $scopeOpener + 1, null, true); while ($end = $phpcsFile->findNext([T_SEMICOLON], $begin + 1, $scopeCloser)) { $statements[] = [ - 'begin' => $begin, - 'end' => $end, + 'begin' => $begin, + 'end' => $end, 'content' => $phpcsFile->getTokensAsString($begin, $end - $begin + 1), ]; $begin = $phpcsFile->findNext(Tokens::$emptyTokens, $end + 1, null, true); diff --git a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php index fa03dac7..e434c060 100644 --- a/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php +++ b/src/ZendCodingStandard/Sniffs/Commenting/FunctionCommentSniff.php @@ -178,10 +178,10 @@ private function processTagOrder(File $phpcsFile, int $commentStart) : void } $data[] = [ - 'tag' => strtolower($tokens[$tag]['content']), + 'tag' => strtolower($tokens[$tag]['content']), 'token' => $tag, 'first' => $phpcsFile->findFirstOnLine([], $tag, true), - 'last' => $last, + 'last' => $last, ]; next($tags); diff --git a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php index 7b2db756..e764c13d 100644 --- a/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Formatting/UnnecessaryParenthesesSniff.php @@ -221,9 +221,9 @@ public function process(File $phpcsFile, $stackPtr) + Tokens::$booleanOperators + [ T_BITWISE_AND => T_BITWISE_AND, - T_BITWISE_OR => T_BITWISE_OR, + T_BITWISE_OR => T_BITWISE_OR, T_BITWISE_XOR => T_BITWISE_XOR, - T_COALESCE => T_COALESCE, + T_COALESCE => T_COALESCE, T_INLINE_ELSE => T_INLINE_ELSE, T_INLINE_THEN => T_INLINE_THEN, ], @@ -247,7 +247,7 @@ public function process(File $phpcsFile, $stackPtr) Tokens::$assignmentTokens + Tokens::$booleanOperators + [ - T_COALESCE => T_COALESCE, + T_COALESCE => T_COALESCE, T_INLINE_ELSE => T_INLINE_ELSE, T_INLINE_THEN => T_INLINE_THEN, ], diff --git a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php index 4f243ea3..c9c59997 100644 --- a/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -177,10 +177,10 @@ private function getUseStatements(File $phpcsFile, int $scopePtr) : array $uses[] = [ 'ptrUse' => $use, - 'name' => trim($phpcsFile->getTokensAsString($startOfName, $endOfScope - $startOfName)), + 'name' => trim($phpcsFile->getTokensAsString($startOfName, $endOfScope - $startOfName)), 'ptrEnd' => $endOfScope, 'string' => trim($phpcsFile->getTokensAsString($use, $endOfScope - $use + 1)), - 'type' => $type, + 'type' => $type, ]; $start = $endOfScope; diff --git a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php index 327fd6b4..395bac6d 100644 --- a/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php +++ b/src/ZendCodingStandard/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -19,15 +19,15 @@ class ValidVariableNameSniff extends AbstractVariableSniff * @var array */ protected $phpReservedVars = [ - '_SERVER' => true, - '_GET' => true, - '_POST' => true, + '_SERVER' => true, + '_GET' => true, + '_POST' => true, '_REQUEST' => true, '_SESSION' => true, - '_ENV' => true, - '_COOKIE' => true, - '_FILES' => true, - 'GLOBALS' => true, + '_ENV' => true, + '_COOKIE' => true, + '_FILES' => true, + 'GLOBALS' => true, ]; /** diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php index 206633b4..2d68bbbc 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalConstantSniff.php @@ -206,7 +206,7 @@ private function importConstant(File $phpcsFile, int $stackPtr, string $constant $this->importedConstants[$constantName] = [ 'name' => $constantName, - 'fqn' => $constantName, + 'fqn' => $constantName, ]; } } diff --git a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php index c9f899c6..566c0ccd 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/ImportInternalFunctionSniff.php @@ -194,7 +194,7 @@ private function importFunction(File $phpcsFile, int $stackPtr, string $function $this->importedFunctions[$functionName] = [ 'name' => $functionName, - 'fqn' => $functionName, + 'fqn' => $functionName, ]; } } diff --git a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php index e44d0712..33afebd9 100644 --- a/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php +++ b/src/ZendCodingStandard/Sniffs/PHP/TypeCastingSniff.php @@ -23,8 +23,8 @@ class TypeCastingSniff implements Sniff private $castMap = [ '(boolean)' => '(bool)', '(integer)' => '(int)', - '(real)' => '(float)', - '(double)' => '(float)', + '(real)' => '(float)', + '(double)' => '(float)', ]; /** diff --git a/test/Sniffs/Arrays/DoubleArrowUnitTest.inc b/test/Sniffs/Arrays/DoubleArrowUnitTest.inc new file mode 100644 index 00000000..ef2fb4e2 --- /dev/null +++ b/test/Sniffs/Arrays/DoubleArrowUnitTest.inc @@ -0,0 +1,10 @@ + 'b', 'c'=>'d']; +$m = [ + 'a' => + 'b', + 'c' + => 'd', + 'e' => 'f', +]; diff --git a/test/Sniffs/Arrays/DoubleArrowUnitTest.inc.fixed b/test/Sniffs/Arrays/DoubleArrowUnitTest.inc.fixed new file mode 100644 index 00000000..ce1f6919 --- /dev/null +++ b/test/Sniffs/Arrays/DoubleArrowUnitTest.inc.fixed @@ -0,0 +1,10 @@ + 'b', 'c'=>'d']; +$m = [ + 'a' + => 'b', + 'c' + => 'd', + 'e' => 'f', +]; diff --git a/test/Sniffs/Arrays/DoubleArrowUnitTest.php b/test/Sniffs/Arrays/DoubleArrowUnitTest.php new file mode 100644 index 00000000..05bb16ff --- /dev/null +++ b/test/Sniffs/Arrays/DoubleArrowUnitTest.php @@ -0,0 +1,24 @@ + 1, + 5 => 1, + 9 => 1, + ]; + } + + public function getWarningList(string $testFile = '') : array + { + return []; + } +} diff --git a/test/Sniffs/TestCase.php b/test/Sniffs/TestCase.php index ff18c68b..4653dd65 100644 --- a/test/Sniffs/TestCase.php +++ b/test/Sniffs/TestCase.php @@ -209,10 +209,10 @@ private function generateFailureMessages(LocalFile $file) : array foreach ($lineErrors as $column => $errors) { if (! isset($allProblems[$line])) { $allProblems[$line] = [ - 'expected_errors' => 0, + 'expected_errors' => 0, 'expected_warnings' => 0, - 'found_errors' => [], - 'found_warnings' => [], + 'found_errors' => [], + 'found_warnings' => [], ]; } @@ -241,10 +241,10 @@ private function generateFailureMessages(LocalFile $file) : array foreach ($expectedErrors as $line => $numErrors) { if (! isset($allProblems[$line])) { $allProblems[$line] = [ - 'expected_errors' => 0, + 'expected_errors' => 0, 'expected_warnings' => 0, - 'found_errors' => [], - 'found_warnings' => [], + 'found_errors' => [], + 'found_warnings' => [], ]; } @@ -255,10 +255,10 @@ private function generateFailureMessages(LocalFile $file) : array foreach ($lineWarnings as $column => $warnings) { if (! isset($allProblems[$line])) { $allProblems[$line] = [ - 'expected_errors' => 0, + 'expected_errors' => 0, 'expected_warnings' => 0, - 'found_errors' => [], - 'found_warnings' => [], + 'found_errors' => [], + 'found_warnings' => [], ]; } @@ -287,10 +287,10 @@ private function generateFailureMessages(LocalFile $file) : array foreach ($expectedWarnings as $line => $numWarnings) { if (! isset($allProblems[$line])) { $allProblems[$line] = [ - 'expected_errors' => 0, + 'expected_errors' => 0, 'expected_warnings' => 0, - 'found_errors' => [], - 'found_warnings' => [], + 'found_errors' => [], + 'found_warnings' => [], ]; } From 1ab48b143775fb7f0f584f14b5d02a95dbb363e1 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 29 Mar 2018 07:30:38 +0100 Subject: [PATCH 217/225] Typo fix --- src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php index 03c88d24..3249cb73 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php @@ -201,7 +201,7 @@ protected function processThrowStatements(File $phpcsFile, int $stackPtr) : void if (! $foundThrows) { // It should be disabled if we want to declare implicit throws foreach ($this->throwTags as $ptr => $class) { - $error = 'Function does not throw any exception but has @throw tag'; + $error = 'Function does not throw any exception but has @throws tag'; $phpcsFile->addError($error, $ptr, 'AdditionalThrowTag'); } From de8c234fc3e44958a2f330161ae4720990fbcadc Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 29 Mar 2018 07:35:10 +0100 Subject: [PATCH 218/225] Update LICENSE.md --- LICENSE.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index badc26ea..bd188312 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,16 +1,15 @@ -Copyright (c) 2016, Zend Technologies USA, Inc. - +Copyright (c) 2016-2018, Zend Technologies USA, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -- Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. +- Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. -- Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. +- Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. - Neither the name of Zend Technologies USA, Inc. nor the names of its contributors may be used to endorse or promote products derived from this From 4791944e82d9757a8c1ee489b749708e6b91b849 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 29 Mar 2018 14:11:24 +0100 Subject: [PATCH 219/225] Added support documents in docs/ directory --- CONDUCT.md => docs/CODE_OF_CONDUCT.md | 2 +- docs/CONTRIBUTING.md | 189 ++++++++++++++++++++++++++ docs/ISSUE_TEMPLATE.md | 19 +++ docs/PULL_REQUEST_TEMPLATE.md | 25 ++++ docs/SUPPORT.md | 25 ++++ 5 files changed, 259 insertions(+), 1 deletion(-) rename CONDUCT.md => docs/CODE_OF_CONDUCT.md (96%) create mode 100644 docs/CONTRIBUTING.md create mode 100644 docs/ISSUE_TEMPLATE.md create mode 100644 docs/PULL_REQUEST_TEMPLATE.md create mode 100644 docs/SUPPORT.md diff --git a/CONDUCT.md b/docs/CODE_OF_CONDUCT.md similarity index 96% rename from CONDUCT.md rename to docs/CODE_OF_CONDUCT.md index c663d2be..02fafcd1 100644 --- a/CONDUCT.md +++ b/docs/CODE_OF_CONDUCT.md @@ -1,6 +1,6 @@ # Contributor Code of Conduct -The Zend Framework project adheres to [The Code Manifesto](http://codemanifesto.com) +This project adheres to [The Code Manifesto](http://codemanifesto.com) as its guidelines for contributor interactions. ## The Code Manifesto diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 00000000..c0511a0f --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,189 @@ +# CONTRIBUTING + +## RESOURCES + +If you wish to contribute to this project, please be sure to +read/subscribe to the following resources: + + - [Coding Standards](https://github.com/zendframework/zend-coding-standard) + - [Forums](https://discourse.zendframework.com/c/contributors) + - [Slack](https://zendframework-slack.herokuapp.com) + - [Code of Conduct](CODE_OF_CONDUCT.md) + +If you are working on new features or refactoring +[create a proposal](https://github.com/zendframework/zend-coding-standard/issues/new). + +## RUNNING TESTS + +To run tests: + +- Clone the repository: + + ```console + $ git clone git://github.com/zendframework/zend-coding-standard.git + $ cd zend-coding-standard + ``` + +- Install dependencies via composer: + + ```console + $ composer install + ``` + + If you don't have `composer` installed, please download it from https://getcomposer.org/download/ + +- Run the tests using the "test" command shipped in the `composer.json`: + + ```console + $ composer test + ``` + +You can turn on conditional tests with the `phpunit.xml` file. +To do so: + + - Copy `phpunit.xml.dist` file to `phpunit.xml` + - Edit `phpunit.xml` to enable any specific functionality you + want to test, as well as to provide test values to utilize. + +## Running Coding Standards Checks + +First, ensure you've installed dependencies via composer, per the previous +section on running tests. + +To run CS checks only: + +```console +$ composer cs-check +``` + +To attempt to automatically fix common CS issues: + +```console +$ composer cs-fix +``` + +If the above fixes any CS issues, please re-run the tests to ensure +they pass, and make sure you add and commit the changes after verification. + +## Recommended Workflow for Contributions + +Your first step is to establish a public repository from which we can +pull your work into the master repository. We recommend using +[GitHub](https://github.com), as that is where the component is already hosted. + +1. Setup a [GitHub account](https://github.com/), if you haven't yet +2. Fork the repository (https://github.com/zendframework/zend-coding-standard) +3. Clone the canonical repository locally and enter it. + + ```console + $ git clone git://github.com/zendframework/zend-coding-standard.git + $ cd zend-coding-standard + ``` + +4. Add a remote to your fork; substitute your GitHub username in the command + below. + + ```console + $ git remote add {username} git@github.com:{username}/zend-coding-standard.git + $ git fetch {username} + ``` + +### Keeping Up-to-Date + +Periodically, you should update your fork or personal repository to +match the canonical ZF repository. Assuming you have setup your local repository +per the instructions above, you can do the following: + + +```console +$ git checkout master +$ git fetch origin +$ git rebase origin/master +# OPTIONALLY, to keep your remote up-to-date - +$ git push {username} master:master +``` + +If you're tracking other branches -- for example, the "develop" branch, where +new feature development occurs -- you'll want to do the same operations for that +branch; simply substitute "develop" for "master". + +### Working on a patch + +We recommend you do each new feature or bugfix in a new branch. This simplifies +the task of code review as well as the task of merging your changes into the +canonical repository. + +A typical workflow will then consist of the following: + +1. Create a new local branch based off either your master or develop branch. +2. Switch to your new local branch. (This step can be combined with the + previous step with the use of `git checkout -b`.) +3. Do some work, commit, repeat as necessary. +4. Push the local branch to your remote repository. +5. Send a pull request. + +The mechanics of this process are actually quite trivial. Below, we will +create a branch for fixing an issue in the tracker. + +```console +$ git checkout -b hotfix/9295 +Switched to a new branch 'hotfix/9295' +``` + +... do some work ... + + +```console +$ git commit +``` + +... write your log message ... + + +```console +$ git push {username} hotfix/9295:hotfix/9295 +Counting objects: 38, done. +Delta compression using up to 2 threads. +Compression objects: 100% (18/18), done. +Writing objects: 100% (20/20), 8.19KiB, done. +Total 20 (delta 12), reused 0 (delta 0) +To ssh://git@github.com/{username}/zend-coding-standard.git + b5583aa..4f51698 HEAD -> master +``` + +To send a pull request, you have two options. + +If using GitHub, you can do the pull request from there. Navigate to +your repository, select the branch you just created, and then select the +"Pull Request" button in the upper right. Select the user/organization +"zendframework" (or whatever the upstream organization is) as the recipient. + +#### What branch to issue the pull request against? + +Which branch should you issue a pull request against? + +- For fixes against the stable release, issue the pull request against the + "master" branch. +- For new features, or fixes that introduce new elements to the public API (such + as new public methods or properties), issue the pull request against the + "develop" branch. + +### Branch Cleanup + +As you might imagine, if you are a frequent contributor, you'll start to +get a ton of branches both locally and on your remote. + +Once you know that your changes have been accepted to the master +repository, we suggest doing some cleanup of these branches. + +- Local branch cleanup + + ```console + $ git branch -d + ``` + +- Remote branch removal + + ```console + $ git push {username} : + ``` diff --git a/docs/ISSUE_TEMPLATE.md b/docs/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..3bdc945e --- /dev/null +++ b/docs/ISSUE_TEMPLATE.md @@ -0,0 +1,19 @@ + - [ ] I was not able to find an [open](https://github.com/zendframework/zend-coding-standard/issues?q=is%3Aopen) or [closed](https://github.com/zendframework/zend-coding-standard/issues?q=is%3Aclosed) issue matching what I'm seeing. + - [ ] This is not a question. (Questions should be asked on [slack](https://zendframework.slack.com/) ([Signup for Slack here](https://zendframework-slack.herokuapp.com/)) or our [forums](https://discourse.zendframework.com/).) + +Provide a narrative description of what you are trying to accomplish. + +### Code to reproduce the issue + + + +```php +``` + +### Expected results + + + +### Actual results + + diff --git a/docs/PULL_REQUEST_TEMPLATE.md b/docs/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..f00d90c0 --- /dev/null +++ b/docs/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,25 @@ +Provide a narrative description of what you are trying to accomplish: + +- [ ] Are you fixing a bug? + - [ ] Detail how the bug is invoked currently. + - [ ] Detail the original, incorrect behavior. + - [ ] Detail the new, expected behavior. + - [ ] Base your feature on the `master` branch, and submit against that branch. + - [ ] Add a regression test that demonstrates the bug, and proves the fix. + - [ ] Add a `CHANGELOG.md` entry for the fix. + +- [ ] Are you creating a new feature? + - [ ] Why is the new feature needed? What purpose does it serve? + - [ ] How will users use the new feature? + - [ ] Base your feature on the `develop` branch, and submit against that branch. + - [ ] Add only one feature per pull request; split multiple features over multiple pull requests + - [ ] Add tests for the new feature. + - [ ] Add documentation for the new feature. + - [ ] Add a `CHANGELOG.md` entry for the new feature. + +- [ ] Is this related to quality assurance? + + +- [ ] Is this related to documentation? + + diff --git a/docs/SUPPORT.md b/docs/SUPPORT.md new file mode 100644 index 00000000..8ac51a29 --- /dev/null +++ b/docs/SUPPORT.md @@ -0,0 +1,25 @@ +# Getting Support + +Zend Framework offers three support channels: + +- For real-time questions, use our + [Slack](https://zendframework-slack.herokuapp.com) +- For detailed questions (e.g., those requiring examples) use our + [forums](https://discourse.zendframework.com/c/questions/components) +- To report issues, use this repository's + [issue tracker](https://github.com/zendframework/zend-coding-standard/issues/new) + +**DO NOT** use the issue tracker to ask questions; use Slack or the forums for +that. Questions posed to the issue tracker will be closed. + +When reporting an issue, please include the following details: + +- A narrative description of what you are trying to accomplish. +- The minimum code necessary to reproduce the issue. +- The expected results of exercising that code. +- The actual results received. + +We may ask for additional details: what version of the library you are using, +and what PHP version was used to reproduce the issue. + +You may also submit a failing test case as a pull request. From c6f36c03101e0c67382607a2ba43e063059bd2b5 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 29 Mar 2018 14:50:38 +0100 Subject: [PATCH 220/225] Fixed spaces in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 42235de7..a9484c22 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ For a reference please see: https://github.com/squizlabs/PHP_CodeSniffer/wiki/An ``` * To automatically fix many CS issues: - + ```bash $ composer cs-fix ``` From 6288f38c800f502c4ed1fa59fd698c1a85135c46 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 29 Mar 2018 14:51:09 +0100 Subject: [PATCH 221/225] Removed redundant PHPUnit whitelist config attr --- phpunit.xml.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 91d7dc3c..5fbd71f4 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -10,7 +10,7 @@ - + ./src From e9a19c644186cf4005194ecd545ccd2b074f3b28 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 29 Mar 2018 16:26:40 +0100 Subject: [PATCH 222/225] DeclareStrictTypes fix - changed how autofixer works --- .../Sniffs/Files/DeclareStrictTypesSniff.php | 3 +-- test/Sniffs/Files/DeclareStrictTypesUnitTest.6.inc | 12 ++++++++++++ .../Files/DeclareStrictTypesUnitTest.6.inc.fixed | 14 ++++++++++++++ test/Sniffs/Files/DeclareStrictTypesUnitTest.php | 2 ++ 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 test/Sniffs/Files/DeclareStrictTypesUnitTest.6.inc create mode 100644 test/Sniffs/Files/DeclareStrictTypesUnitTest.6.inc.fixed diff --git a/src/ZendCodingStandard/Sniffs/Files/DeclareStrictTypesSniff.php b/src/ZendCodingStandard/Sniffs/Files/DeclareStrictTypesSniff.php index ea89bbfa..ddf542a7 100644 --- a/src/ZendCodingStandard/Sniffs/Files/DeclareStrictTypesSniff.php +++ b/src/ZendCodingStandard/Sniffs/Files/DeclareStrictTypesSniff.php @@ -6,7 +6,6 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; -use PHP_CodeSniffer\Util\Tokens; use function array_map; use function array_search; @@ -74,7 +73,7 @@ public function process(File $phpcsFile, $stackPtr) $fix = $phpcsFile->addFixableError($error, $stackPtr, 'BelowComment'); if ($fix) { - $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $prev - 1, null, true); + $prev = $phpcsFile->findPrevious([T_OPEN_TAG, T_DOC_COMMENT_CLOSE_TAG], $prev - 1); $this->fix($phpcsFile, $stackPtr, $eos, $prev); } diff --git a/test/Sniffs/Files/DeclareStrictTypesUnitTest.6.inc b/test/Sniffs/Files/DeclareStrictTypesUnitTest.6.inc new file mode 100644 index 00000000..80d39ca5 --- /dev/null +++ b/test/Sniffs/Files/DeclareStrictTypesUnitTest.6.inc @@ -0,0 +1,12 @@ + 1]; case 'DeclareStrictTypesUnitTest.5.inc': return [8 => 1]; + case 'DeclareStrictTypesUnitTest.6.inc': + return [12 => 1]; } return []; From 5131a5aecbd16353ad20d53c845e46babf482742 Mon Sep 17 00:00:00 2001 From: webimpress Date: Mon, 2 Apr 2018 22:22:49 +0200 Subject: [PATCH 223/225] Added Heredoc sniff - tag must be uppercase and cannot contain any spaces --- .../Sniffs/Formatting/HeredocSniff.php | 77 +++++++++++++++++++ test/Sniffs/Formatting/HeredocUnitTest.inc | 31 ++++++++ .../Formatting/HeredocUnitTest.inc.fixed | 31 ++++++++ test/Sniffs/Formatting/HeredocUnitTest.php | 29 +++++++ 4 files changed, 168 insertions(+) create mode 100644 src/ZendCodingStandard/Sniffs/Formatting/HeredocSniff.php create mode 100644 test/Sniffs/Formatting/HeredocUnitTest.inc create mode 100644 test/Sniffs/Formatting/HeredocUnitTest.inc.fixed create mode 100644 test/Sniffs/Formatting/HeredocUnitTest.php diff --git a/src/ZendCodingStandard/Sniffs/Formatting/HeredocSniff.php b/src/ZendCodingStandard/Sniffs/Formatting/HeredocSniff.php new file mode 100644 index 00000000..7516b4e2 --- /dev/null +++ b/src/ZendCodingStandard/Sniffs/Formatting/HeredocSniff.php @@ -0,0 +1,77 @@ +getTokens(); + $content = $tokens[$stackPtr]['content']; + + $expected = preg_replace('/<<<\s+/', '<<<', $tokens[$stackPtr]['content']); + if ($content !== $expected) { + $error = 'Heredoc start tag cannot contain any whitespaces; found "%s", expected "%s"'; + $data = [ + trim($content), + trim($expected), + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Space', $data); + + if ($fix) { + $phpcsFile->fixer->replaceToken($stackPtr, $expected); + } + } + + $expected = strtoupper($content); + if ($content !== $expected) { + if (preg_match('/[a-z][A-Z]/', $content)) { + $error = 'Heredoc tag must be uppercase underscore separated, cannot be camel case'; + $phpcsFile->addError($error, $stackPtr, 'CamelCase'); + } else { + $error = 'Heredoc tag must be uppercase; found "%s"; expected "%s"'; + $data = [ + trim($content), + trim($expected), + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Uppercase', $data); + + if ($fix) { + $closer = $tokens[$stackPtr]['scope_closer']; + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($stackPtr, $expected); + $phpcsFile->fixer->replaceToken($closer, strtoupper($tokens[$closer]['content'])); + $phpcsFile->fixer->endChangeset(); + } + } + } + } +} diff --git a/test/Sniffs/Formatting/HeredocUnitTest.inc b/test/Sniffs/Formatting/HeredocUnitTest.inc new file mode 100644 index 00000000..68a8dd6b --- /dev/null +++ b/test/Sniffs/Formatting/HeredocUnitTest.inc @@ -0,0 +1,31 @@ + 1, + 6 => 1, + 9 => 1, + 12 => 1, + 21 => 1, + 24 => 1, + 27 => 2, + 30 => 2, + ]; + } + + public function getWarningList(string $testFile = '') : array + { + return []; + } +} From 2800f34b66d770c238be74ebfe1c94a0f7cf5daf Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 4 Apr 2018 14:01:59 +0100 Subject: [PATCH 224/225] Added more cases for ScopeIndent sniff --- .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 9 +++++-- .../Sniffs/WhiteSpace/ScopeIndentUnitTest.inc | 25 +++++++++++++++++++ .../WhiteSpace/ScopeIndentUnitTest.inc.fixed | 25 +++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php index 81057366..face60d9 100644 --- a/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/ZendCodingStandard/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -25,6 +25,7 @@ use const T_CLOSE_CURLY_BRACKET; use const T_CLOSE_PARENTHESIS; use const T_CLOSE_SHORT_ARRAY; +use const T_CLOSE_SQUARE_BRACKET; use const T_CLOSURE; use const T_COLON; use const T_COMMA; @@ -48,6 +49,7 @@ use const T_OPEN_CURLY_BRACKET; use const T_OPEN_PARENTHESIS; use const T_OPEN_SHORT_ARRAY; +use const T_OPEN_SQUARE_BRACKET; use const T_OPEN_TAG; use const T_RETURN; use const T_SELF; @@ -777,13 +779,16 @@ private function fp(File $phpcsFile, int $ptr) : ?int while (--$ptr) { if ($tokens[$ptr]['code'] === T_CLOSE_PARENTHESIS) { $ptr = $tokens[$ptr]['parenthesis_opener']; - } elseif ($tokens[$ptr]['code'] === T_CLOSE_CURLY_BRACKET) { + } elseif ($tokens[$ptr]['code'] === T_CLOSE_CURLY_BRACKET + || $tokens[$ptr]['code'] === T_CLOSE_SHORT_ARRAY + || $tokens[$ptr]['code'] === T_CLOSE_SQUARE_BRACKET + ) { $ptr = $tokens[$ptr]['bracket_opener']; } elseif ($tokens[$ptr]['code'] === T_OBJECT_OPERATOR) { return $tokens[$ptr]['column']; } elseif (in_array( $tokens[$ptr]['code'], - [T_SEMICOLON, T_OPEN_PARENTHESIS], + [T_SEMICOLON, T_OPEN_CURLY_BRACKET, T_OPEN_PARENTHESIS, T_OPEN_SHORT_ARRAY, T_OPEN_SQUARE_BRACKET], true )) { break; diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc index 54211edc..b05d45ce 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc @@ -531,3 +531,28 @@ yield 'key' => (new DateTime( })() )) ->format('Y'); + +$abc = [ + $test + ->abc() + ->def(), +]; + +$def = function ($a) { + $a + ->a() + ->b(); +}; + +$ghi = [ + [ + function () { + }, + $hey + ->a() + ->b(), + ], + $hola + ->c() + ->d(), +]; diff --git a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed index 934d5e58..b084bba0 100644 --- a/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed +++ b/test/Sniffs/WhiteSpace/ScopeIndentUnitTest.inc.fixed @@ -529,3 +529,28 @@ yield 'key' => (new DateTime( })() )) ->format('Y'); + +$abc = [ + $test + ->abc() + ->def(), +]; + +$def = function ($a) { + $a + ->a() + ->b(); +}; + +$ghi = [ + [ + function () { + }, + $hey + ->a() + ->b(), + ], + $hola + ->c() + ->d(), +]; From 4d14354447e53d1b49693edd64951ac5bd059e6d Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 4 Apr 2018 14:31:17 +0100 Subject: [PATCH 225/225] Improvements for Throw sniff Better analyze if throw tag should be added on the function --- .../Sniffs/Functions/ThrowsSniff.php | 64 ++++++++++++++++++- test/Sniffs/Functions/ThrowsUnitTest.inc | 27 ++++++++ .../Sniffs/Functions/ThrowsUnitTest.inc.fixed | 27 ++++++++ 3 files changed, 116 insertions(+), 2 deletions(-) diff --git a/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php b/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php index 3249cb73..78a04d28 100644 --- a/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php +++ b/src/ZendCodingStandard/Sniffs/Functions/ThrowsSniff.php @@ -19,11 +19,20 @@ use const T_BITWISE_OR; use const T_CATCH; +use const T_CLOSE_CURLY_BRACKET; +use const T_CLOSE_PARENTHESIS; +use const T_CLOSE_SHORT_ARRAY; +use const T_CLOSE_SQUARE_BRACKET; use const T_CLOSURE; use const T_DOC_COMMENT_STRING; use const T_FUNCTION; use const T_NEW; use const T_NS_SEPARATOR; +use const T_OPEN_CURLY_BRACKET; +use const T_OPEN_PARENTHESIS; +use const T_OPEN_SHORT_ARRAY; +use const T_OPEN_SQUARE_BRACKET; +use const T_SEMICOLON; use const T_STRING; use const T_THROW; use const T_TRY; @@ -132,7 +141,7 @@ protected function processThrowStatements(File $phpcsFile, int $stackPtr) : void } // The throw statement is in another scope. - if (! $this->isLastScope($tokens[$throw]['conditions'], $stackPtr)) { + if (! $this->isLastScope($phpcsFile, $tokens[$throw]['conditions'], $stackPtr)) { continue; } @@ -305,16 +314,67 @@ private function getExceptions(File $phpcsFile, int $from, int $to) : array * @param string[] $conditions * @param int $scope Scope to check in conditions. */ - private function isLastScope(array $conditions, int $scope) : bool + private function isLastScope(File $phpcsFile, array $conditions, int $scope) : bool { + $tokens = $phpcsFile->getTokens(); + foreach (array_reverse($conditions, true) as $ptr => $code) { if ($code !== T_FUNCTION && $code !== T_CLOSURE && $code !== T_TRY) { continue; } + if ($code === T_CLOSURE && $ptr !== $scope) { + // Check if closure is called. + $afterClosure = $phpcsFile->findNext( + Tokens::$emptyTokens, + $tokens[$ptr]['scope_closer'] + 1, + null, + true + ); + if ($afterClosure && $tokens[$afterClosure]['code'] === T_CLOSE_PARENTHESIS) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $afterClosure + 1, null, true); + if ($next && $tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + return true; + } + } + + // Check if closure is passed to function/class. + if (($token = $this->findPrevious($phpcsFile, $ptr)) + && in_array($tokens[$token]['code'], [T_STRING, T_VARIABLE], true) + ) { + return true; + } + } + return $ptr === $scope; } return false; } + + private function findPrevious(File $phpcsFile, int $ptr) : ?int + { + $tokens = $phpcsFile->getTokens(); + + while (--$ptr) { + if ($tokens[$ptr]['code'] === T_CLOSE_PARENTHESIS) { + $ptr = $tokens[$ptr]['parenthesis_opener']; + } elseif ($tokens[$ptr]['code'] === T_CLOSE_CURLY_BRACKET + || $tokens[$ptr]['code'] === T_CLOSE_SHORT_ARRAY + || $tokens[$ptr]['code'] === T_CLOSE_SQUARE_BRACKET + ) { + $ptr = $tokens[$ptr]['bracket_opener']; + } elseif ($tokens[$ptr]['code'] === T_OPEN_PARENTHESIS) { + return $phpcsFile->findPrevious(Tokens::$emptyTokens, $ptr - 1, null, true); + } elseif (in_array( + $tokens[$ptr]['code'], + [T_SEMICOLON, T_OPEN_CURLY_BRACKET, T_OPEN_SHORT_ARRAY, T_OPEN_SQUARE_BRACKET], + true + )) { + break; + } + } + + return null; + } } diff --git a/test/Sniffs/Functions/ThrowsUnitTest.inc b/test/Sniffs/Functions/ThrowsUnitTest.inc index c4b1278a..4a6204cd 100644 --- a/test/Sniffs/Functions/ThrowsUnitTest.inc +++ b/test/Sniffs/Functions/ThrowsUnitTest.inc @@ -283,4 +283,31 @@ class ThrowUnitTest { throw new Ex\Exception; } + + public function closure() + { + return function () { + throw new Exception(); + }; + } + + /** + * @throws Exception + */ + public function calledClosure() + { + (function () { + throw new Exception(); + })(); + } + + /** + * @throws Exception + */ + public function callback(array $arr) + { + return array_filter([] + array_filter($arr), function () { + throw new Exception(); + }); + } } diff --git a/test/Sniffs/Functions/ThrowsUnitTest.inc.fixed b/test/Sniffs/Functions/ThrowsUnitTest.inc.fixed index ed5e03b0..b05e1a2f 100644 --- a/test/Sniffs/Functions/ThrowsUnitTest.inc.fixed +++ b/test/Sniffs/Functions/ThrowsUnitTest.inc.fixed @@ -283,4 +283,31 @@ class ThrowUnitTest { throw new Ex\Exception; } + + public function closure() + { + return function () { + throw new Exception(); + }; + } + + /** + * @throws Exception + */ + public function calledClosure() + { + (function () { + throw new Exception(); + })(); + } + + /** + * @throws Exception + */ + public function callback(array $arr) + { + return array_filter([] + array_filter($arr), function () { + throw new Exception(); + }); + } }