From 2c3f5736439b47dec4598e1be1836af43317ffe2 Mon Sep 17 00:00:00 2001 From: Gary Jones Date: Fri, 4 Aug 2017 12:11:13 +0100 Subject: [PATCH] Add ReturnTypeSpacing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only slightly adapted from the work MichaƂ Bundyra (@webimpress) did for the Zend Coding Standard. Required format for WordPress is the same as most others in the PHP community: - no spaces before the colon - exactly one space after colon before return type - no space after nullable operator - simple types should be given as lowercase Fixes #547. --- .../WhiteSpace/ReturnTypeSpacingSniff.php | 142 ++++++++++++++++++ .../WhiteSpace/ReturnTypeSpacingUnitTest.inc | 84 +++++++++++ .../ReturnTypeSpacingUnitTest.inc.fixed | 80 ++++++++++ .../WhiteSpace/ReturnTypeSpacingUnitTest.php | 78 ++++++++++ 4 files changed, 384 insertions(+) create mode 100644 WordPress/Sniffs/WhiteSpace/ReturnTypeSpacingSniff.php create mode 100644 WordPress/Tests/WhiteSpace/ReturnTypeSpacingUnitTest.inc create mode 100644 WordPress/Tests/WhiteSpace/ReturnTypeSpacingUnitTest.inc.fixed create mode 100644 WordPress/Tests/WhiteSpace/ReturnTypeSpacingUnitTest.php diff --git a/WordPress/Sniffs/WhiteSpace/ReturnTypeSpacingSniff.php b/WordPress/Sniffs/WhiteSpace/ReturnTypeSpacingSniff.php new file mode 100644 index 0000000000..2ffb4d04bf --- /dev/null +++ b/WordPress/Sniffs/WhiteSpace/ReturnTypeSpacingSniff.php @@ -0,0 +1,142 @@ +phpcsFile->findPrevious( T_COLON, $stackPtr - 1 ); + + // Space before colon disallowed. + if ( T_CLOSE_PARENTHESIS !== $this->tokens[ $colon - 1 ][ 'code' ] ) { + $error = 'There must be no space before colon before a return type.'; + $fix = $this->phpcsFile->addFixableError( $error, $colon - 1, 'SpaceBeforeColon' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + $token = $colon - 1; + do { + $this->phpcsFile->fixer->replaceToken( $token, '' ); + -- $token; + } while ( $this->tokens[ $token ][ 'code' ] !== T_CLOSE_PARENTHESIS ); + $this->phpcsFile->fixer->endChangeset(); + } + } + + // Only one space after colon. + if ( T_WHITESPACE !== $this->tokens[ $colon + 1 ][ 'code' ] ) { + $error = 'There must be a space after colon and before return type declaration.'; + $fix = $this->phpcsFile->addFixableError( $error, $colon, 'NoSpaceAfterColon' ); + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $colon, ' ' ); + } + } elseif ( ' ' !== $this->tokens[ $colon + 1 ][ 'content' ] ) { + $error = 'There must be exactly one space after colon and before return type declaration.'; + $fix = $this->phpcsFile->addFixableError( $error, $colon + 1, 'TooManySpacesAfterColon' ); + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( $colon + 1, ' ' ); + } + } + + $nullable = $this->phpcsFile->findNext( T_NULLABLE, $colon + 1, $stackPtr ); + if ( $nullable ) { + // Check if there is space after nullable operator. + if ( $this->tokens[ $nullable + 1 ][ 'code' ] === T_WHITESPACE ) { + $error = 'Space is not not allowed after nullable operator.'; + $fix = $this->phpcsFile->addFixableError( $error, $nullable + 1, 'SpaceAfterNullable' ); + if ( $fix ) { + $this->phpcsFile->fixer->replaceToken( $nullable + 1, '' ); + } + } + } + + $first = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $nullable ?: $colon ) + 1, null, true ); + $end = $this->phpcsFile->findNext( [ T_SEMICOLON, T_OPEN_CURLY_BRACKET ], $stackPtr + 1 ); + $last = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $end - 1, null, true ); + $invalid = $this->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 = array( $this->tokens[ $invalid ][ 'type' ] ); + $fix = $this->phpcsFile->addFixableError( $error, $invalid, 'InvalidToken', $data ); + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( $invalid, '' ); + } + + return; + } + + $returnType = trim( $this->phpcsFile->getTokensAsString( $first, $last - $first + 1 ) ); + + if ( $first === $last + && in_array( strtolower( $returnType ), $this->simple_return_types, true ) + && ! in_array( $returnType, $this->simple_return_types, true ) + ) { + $error = 'Simple return type must be lowercase. Found "%s", expected "%s"'; + $data = array( + $returnType, + strtolower( $returnType ), + ); + $fix = $this->phpcsFile->addFixableError( $error, $first, 'LowerCaseSimpleType', $data ); + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( $stackPtr, strtolower( $returnType ) ); + } + } + } +} diff --git a/WordPress/Tests/WhiteSpace/ReturnTypeSpacingUnitTest.inc b/WordPress/Tests/WhiteSpace/ReturnTypeSpacingUnitTest.inc new file mode 100644 index 0000000000..a565b2aac7 --- /dev/null +++ b/WordPress/Tests/WhiteSpace/ReturnTypeSpacingUnitTest.inc @@ -0,0 +1,84 @@ + => + */ + public function getErrorList() { + return array( + 4 => 1, + 5 => 1, + 6 => 1, + 8 => 1, + 9 => 1, + 10 => 1, + 29 => 2, + 38 => 1, + 44 => 2, + 52 => 2, + 57 => 2, + 58 => 2, + 59 => 2, + 60 => 3, + 61 => 3, + 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, + 76 => 2, + 77 => 1, + 79 => 2, + 80 => 1, + 82 => 1, + 83 => 3, + ); + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + + } + +}