-
-
Notifications
You must be signed in to change notification settings - Fork 494
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
Showing
4 changed files
with
384 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
<?php | ||
/** | ||
* WordPress Coding Standard. | ||
* | ||
* @package WPCS\WordPressCodingStandards | ||
* @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards | ||
* @license https://opensource.org/licenses/MIT MIT | ||
*/ | ||
|
||
namespace WordPress\Sniffs\WhiteSpace; | ||
|
||
use PHP_CodeSniffer_Tokens as Tokens; | ||
use WordPress\Sniff; | ||
|
||
/** | ||
* Enforces spacing around return types. | ||
* | ||
* @package WPCS\WordPressCodingStandards | ||
* | ||
* @since 0.14.0 | ||
* | ||
* @link https://github.com/zendframework/zend-coding-standard/blob/52b435c714879609262aa36b004c4075cd967acc/src/ZendCodingStandard/Sniffs/Formatting/ReturnTypeSniff.php | ||
*/ | ||
class ReturnTypeSpacingSniff extends Sniff { | ||
/** | ||
* Simple return types. | ||
* | ||
* @since 0.14.0 | ||
* | ||
* @var string[] | ||
*/ | ||
private $simple_return_types = array( | ||
'void', | ||
'int', | ||
'float', | ||
'double', | ||
'string', | ||
'array', | ||
'iterable', | ||
'callable', | ||
'parent', | ||
'self', | ||
'bool', | ||
); | ||
|
||
/** | ||
* Returns an array of tokens this test wants to listen for. | ||
* | ||
* @return array | ||
*/ | ||
public function register() { | ||
return array( | ||
T_RETURN_TYPE, | ||
); | ||
} | ||
|
||
/** | ||
* Processes this test, when one of its tokens is encountered. | ||
* | ||
* @param int $stackPtr The position of the current token in the stack. | ||
* | ||
* @return void | ||
*/ | ||
public function process_token( $stackPtr ) { | ||
$colon = (int) $this->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 ) ); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<?php | ||
|
||
function fooa(): array {} // Good | ||
function foob() : array {} // Bad | ||
function fooc() : array {} // Bad | ||
function food() | ||
: array {} // Bad | ||
function fooe():array {} // Bad | ||
function foof(): array {} // Bad | ||
function foog(): | ||
array {} // Bad | ||
|
||
// Don't touch case statements here. | ||
$v = 1; | ||
switch ($v) { | ||
case 1: | ||
$x = $f1(-1 * $v); | ||
break; | ||
case (2) : | ||
$x = $f2(-1 * $v, $v); | ||
break; | ||
default: | ||
$x = $f1($v) + $f2(-1 * $v, $v); | ||
break; | ||
} | ||
|
||
class ReturnType | ||
{ | ||
public function method() :array | ||
{ | ||
return []; | ||
} | ||
|
||
private function priv( | ||
$a, | ||
$b | ||
) | ||
: int { | ||
return $a * $b; | ||
} | ||
} | ||
|
||
$c = new class() { | ||
public function method() : | ||
float { | ||
return mt_rand(); | ||
} | ||
}; | ||
|
||
abstract class AbsCla | ||
{ | ||
abstract public function x() :bool; | ||
} | ||
|
||
interface MyInterface | ||
{ | ||
public function a():vOid; | ||
public function b() : Int; | ||
public function c() :?int; | ||
public function d() :Float; | ||
public function e() :? float; | ||
public function f():Double; | ||
public function g():?double; | ||
public function h():Array; | ||
public function i() : ?array; | ||
public function j():String; | ||
public function k():?string; | ||
public function l():Parent; | ||
public function m():?parent; | ||
public function n():Callable; | ||
public function o():?callable; | ||
public function p():Bool; | ||
public function q():?bool; | ||
public function r():Self; | ||
public function s():?self; | ||
public function t():Iterable; | ||
public function u():?iterable; | ||
|
||
public function v($a) : \DateTime; | ||
public function w():?\DateTime; | ||
|
||
public function y($a, $b, $c) : \My\TestClass; | ||
public function z():? \ReturnType \MyType; | ||
} |
80 changes: 80 additions & 0 deletions
80
WordPress/Tests/WhiteSpace/ReturnTypeSpacingUnitTest.inc.fixed
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<?php | ||
|
||
function fooa(): array {} // Good | ||
function foob(): array {} // Bad | ||
function fooc(): array {} // Bad | ||
function food(): array {} // Bad | ||
function fooe(): array {} // Bad | ||
function foof(): array {} // Bad | ||
function foog(): array {} // Bad | ||
|
||
// Don't touch case statements here. | ||
$v = 1; | ||
switch ($v) { | ||
case 1: | ||
$x = $f1(-1 * $v); | ||
break; | ||
case (2) : | ||
$x = $f2(-1 * $v, $v); | ||
break; | ||
default: | ||
$x = $f1($v) + $f2(-1 * $v, $v); | ||
break; | ||
} | ||
|
||
class ReturnType | ||
{ | ||
public function method(): array | ||
{ | ||
return []; | ||
} | ||
|
||
private function priv( | ||
$a, | ||
$b | ||
): int { | ||
return $a * $b; | ||
} | ||
} | ||
|
||
$c = new class() { | ||
public function method(): float { | ||
return mt_rand(); | ||
} | ||
}; | ||
|
||
abstract class AbsCla | ||
{ | ||
abstract public function x(): bool; | ||
} | ||
|
||
interface MyInterface | ||
{ | ||
public function a(): void; | ||
public function b(): int; | ||
public function c(): ?int; | ||
public function d(): float; | ||
public function e(): ?float; | ||
public function f(): double; | ||
public function g(): ?double; | ||
public function h(): array; | ||
public function i(): ?array; | ||
public function j(): string; | ||
public function k(): ?string; | ||
public function l(): parent; | ||
public function m(): ?parent; | ||
public function n(): callable; | ||
public function o(): ?callable; | ||
public function p(): bool; | ||
public function q(): ?bool; | ||
public function r(): self; | ||
public function s(): ?self; | ||
public function t(): iterable; | ||
public function u(): ?iterable; | ||
|
||
public function v($a): \DateTime; | ||
public function w(): ?\DateTime; | ||
|
||
public function y($a, $b, $c): \My\TestClass; | ||
public function z(): ?\ReturnType\MyType; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<?php | ||
/** | ||
* Unit test class for WordPress Coding Standard. | ||
* | ||
* @package WPCS\WordPressCodingStandards | ||
* @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards | ||
* @license https://opensource.org/licenses/MIT MIT | ||
*/ | ||
|
||
namespace WordPress\Tests\WhiteSpace; | ||
|
||
use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; | ||
|
||
/** | ||
* Unit test class for the ReturnTypeSpacing sniff. | ||
* | ||
* @package WPCS\WordPressCodingStandards | ||
* | ||
* @since 0.14.0 | ||
*/ | ||
class ReturnTypeSpacingUnitTest extends AbstractSniffUnitTest { | ||
|
||
/** | ||
* Returns the lines where errors should occur. | ||
* | ||
* @return array <int line number> => <int number of errors> | ||
*/ | ||
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 <int line number> => <int number of warnings> | ||
*/ | ||
public function getWarningList() { | ||
return array(); | ||
|
||
} | ||
|
||
} |