diff --git a/MO4/Sniffs/Formatting/ArrayAlignmentSniff.php b/MO4/Sniffs/Arrays/ArrayDoubleArrowAlignmentSniff.php similarity index 88% rename from MO4/Sniffs/Formatting/ArrayAlignmentSniff.php rename to MO4/Sniffs/Arrays/ArrayDoubleArrowAlignmentSniff.php index 7cd980cc..faa049e8 100644 --- a/MO4/Sniffs/Formatting/ArrayAlignmentSniff.php +++ b/MO4/Sniffs/Arrays/ArrayDoubleArrowAlignmentSniff.php @@ -12,14 +12,14 @@ * @version GIT: master * @link https://github.com/Mayflower/mo4-coding-standard */ -namespace MO4\Sniffs\Formatting; +namespace MO4\Sniffs\Arrays; use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens as PHP_CodeSniffer_Tokens; /** - * Array Alignment sniff. + * Array Double Arrow Alignment sniff. * * '=>' must be aligned in arrays, and the key and the '=>' must be in the same line * @@ -30,7 +30,7 @@ * @license http://spdx.org/licenses/MIT MIT License * @link https://github.com/Mayflower/mo4-coding-standard */ -class ArrayAlignmentSniff implements Sniff +class ArrayDoubleArrowAlignmentSniff implements Sniff { /** * Define all types of arrays. @@ -80,21 +80,6 @@ public function process(File $phpcsFile, $stackPtr) if ($tokens[$start]['line'] === $tokens[$end]['line']) { return; - } if ($tokens[($end - 2)]['line'] === $tokens[$end]['line']) { - if ($current['code'] === T_ARRAY) { - $arrayBrackets = 'parenthesis'; - } else { - $arrayBrackets = 'bracket'; - } - - $phpcsFile->addError( - sprintf( - 'closing %s of array must in own line', - $arrayBrackets - ), - $end, - 'ClosingMustBeInOwnLine' - ); } $assignments = array(); diff --git a/MO4/Sniffs/Arrays/MultiLineArraySniff.php b/MO4/Sniffs/Arrays/MultiLineArraySniff.php new file mode 100644 index 00000000..a026f9b8 --- /dev/null +++ b/MO4/Sniffs/Arrays/MultiLineArraySniff.php @@ -0,0 +1,121 @@ + + * @license http://spdx.org/licenses/MIT MIT License + * @version GIT: master + * @link https://github.com/Mayflower/mo4-coding-standard + */ +namespace MO4\Sniffs\Arrays; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +/** + * Multi Line Array sniff. + * + * @category PHP + * @package PHP_CodeSniffer-MO4 + * @author Xaver Loppenstedt + * @copyright 2013-2017 Xaver Loppenstedt, some rights reserved. + * @license http://spdx.org/licenses/MIT MIT License + * @link https://github.com/Mayflower/mo4-coding-standard + */ +class MultiLineArraySniff implements Sniff +{ + /** + * Define all types of arrays. + * + * @var array + */ + protected $arrayTokens = array( + T_ARRAY, + T_OPEN_SHORT_ARRAY, + ); + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array(int) + * @see Tokens.php + */ + public function register() + { + return $this->arrayTokens; + + }//end 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 + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $current = $tokens[$stackPtr]; + + if ($current['code'] === T_ARRAY) { + $arrayType = 'parenthesis'; + $start = $current['parenthesis_opener']; + $end = $current['parenthesis_closer']; + } else { + $arrayType = 'bracket'; + $start = $current['bracket_opener']; + $end = $current['bracket_closer']; + } + + if ($tokens[$start]['line'] === $tokens[$end]['line']) { + return; + } + + if ($tokens[($start + 2)]['line'] === $tokens[$start]['line']) { + $fixable = $phpcsFile->addFixableError( + sprintf( + 'opening %s of multi line array must be followed by newline', + $arrayType + ), + $start, + 'OpeningMustBeFollowedByNewline' + ); + + if ($fixable === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($start); + $phpcsFile->fixer->endChangeset(); + } + } + + if ($tokens[($end - 2)]['line'] === $tokens[$end]['line']) { + $fixable = $phpcsFile->addFixableError( + sprintf( + 'closing %s of multi line array must in own line', + $arrayType + ), + $end, + 'ClosingMustBeInOwnLine' + ); + + if ($fixable === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewlineBefore($end); + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/MO4/Tests/Formatting/ArrayAlignmentUnitTest.fail.inc b/MO4/Tests/Arrays/ArrayDoubleArrowAlignmentUnitTest.fail.inc similarity index 80% rename from MO4/Tests/Formatting/ArrayAlignmentUnitTest.fail.inc rename to MO4/Tests/Arrays/ArrayDoubleArrowAlignmentUnitTest.fail.inc index 2f6d5357..459b611c 100644 --- a/MO4/Tests/Formatting/ArrayAlignmentUnitTest.fail.inc +++ b/MO4/Tests/Arrays/ArrayDoubleArrowAlignmentUnitTest.fail.inc @@ -135,21 +135,3 @@ $a = [ 98765432 => 'fail', ]; - -$values = [ - 'Test:1' => [ - 'object_id' => 1, - 'object_class' => 'Test', - 'object_class_name' => 'TestClass', - 'object_name' => 'TestObject', - 'id' => 'Test:1', ], - 'Test:2' => [ - 'object_id' => 2, - 'object_class' => 'Test', - 'object_class_name' => 'TestClass', - 'object_name' => 'TestObject', - 'id' => 'Test:2', ], ]; - - -$fail = array( - 1); diff --git a/MO4/Tests/Arrays/ArrayDoubleArrowAlignmentUnitTest.fail.inc.fixed b/MO4/Tests/Arrays/ArrayDoubleArrowAlignmentUnitTest.fail.inc.fixed new file mode 100644 index 00000000..459b611c --- /dev/null +++ b/MO4/Tests/Arrays/ArrayDoubleArrowAlignmentUnitTest.fail.inc.fixed @@ -0,0 +1,137 @@ + 1, + 'four' => 4, +]; + +$a = [ + 'one' => 1, + 2, + 'four' => 4, +]; + +// bad +$a = [ + 'one' => 1, 'two' => 2, + 'three' => 1, 'four' => 4, +]; + +$a = [ + 'one' => 1, + 2, + 'four' /* comment */ => 4, +]; + +$a = [ + 'one' => 1, + 2, + // comment + 'four' => 4, +]; + +$a = [ + 2, + 'four' => 4, + // comment + 'one' => /* comment */ + 1, +]; + +$a = array( + 'short' => 1, + 'verylongerkey' => 2, + 'x' => 3, +); + +$a = [ + 'short' => 1, + 'verylongerkey' => 2, + 'x' => 3, +]; + +$a = array( + 'short' => 1, + 'verylongerkey' => 2, + 'array' => array( + 'val1' => 1, + 'val112' => 1, + 'val11234567' => 1, + 'v' => 1, + ), + 'x' => 3, +); + +$a = [ + 'short' => 1, + 'verylongerkey' => 2, + 'array' => [ + 'val1' => 1, + 'val112' => 1, + 'val1123456' => 1, + 'v' => 1, + ], + 'x' => 3, +]; + +$a = [ + 'short' => 1, + 'verylongerkey' => 2, + 'array' => array( + 'val1' => 1, + 'val112' => 1, + 'val11234567' => 1, + 'v' => 1, + ), + 'x' => 3, +]; + +$a = array( + 'short' => 1, + 'verylongerkey' => 2, + 'array' => [ + 'val1' => 1, + 'val112' => 1, + 'val1123' => 1, + 'v' => 1, + ], + 'x' => 3, +); + +$a = [ + 0 => [ 1 => 'O', 0 => 'O'], + 1 => [ 1 => 'O', 0 => 'I'], + 2 => [ 1 => 'I', 0 => 'O'], + 3 => [ 1 => 'I', 0 => 'I'], +]; + +foreach ($x as $k => $v) { + +} + +$a = [ + function () { + $b = [ + 'one' => 1, + 'four' => 4, + ]; + foreach ($b as $k => $v) { + } + $bar = [ + 'one' => 1, + 'four' => 4, + ]; + foreach ($bar as $key => $value) { + } + }, + function () { + }, + 'one' => 1, + 2, + 'four' => 2, + 123456789 + /* bla */ => 'fail', + 98765432 + => 'fail', +]; diff --git a/MO4/Tests/Formatting/ArrayAlignmentUnitTest.pass.inc b/MO4/Tests/Arrays/ArrayDoubleArrowAlignmentUnitTest.pass.inc similarity index 99% rename from MO4/Tests/Formatting/ArrayAlignmentUnitTest.pass.inc rename to MO4/Tests/Arrays/ArrayDoubleArrowAlignmentUnitTest.pass.inc index 95683577..fc39ee3d 100644 --- a/MO4/Tests/Formatting/ArrayAlignmentUnitTest.pass.inc +++ b/MO4/Tests/Arrays/ArrayDoubleArrowAlignmentUnitTest.pass.inc @@ -126,4 +126,4 @@ $a = [ 'one' => 1, 2, 'four' => 2, -]; \ No newline at end of file +]; diff --git a/MO4/Tests/Formatting/ArrayAlignmentUnitTest.php b/MO4/Tests/Arrays/ArrayDoubleArrowAlignmentUnitTest.php similarity index 87% rename from MO4/Tests/Formatting/ArrayAlignmentUnitTest.php rename to MO4/Tests/Arrays/ArrayDoubleArrowAlignmentUnitTest.php index 3868f1ab..0d5b6ece 100644 --- a/MO4/Tests/Formatting/ArrayAlignmentUnitTest.php +++ b/MO4/Tests/Arrays/ArrayDoubleArrowAlignmentUnitTest.php @@ -13,8 +13,13 @@ * @link https://github.com/Mayflower/mo4-coding-standard */ +namespace MO4\Tests\Arrays; + +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + /** - * Unit test class for the ArrayValueAlignment sniff. + * Unit test class for @see ArrayDoubleArrowAlignmentSniff * * A sniff unit test checks a .inc file for expected violations of a single * coding standard. Expected errors and warnings are stored in this class. @@ -22,16 +27,11 @@ * @category PHP * @package PHP_CodeSniffer-MO4 * @author Xaver Loppenstedt - * @copyright 2013 Xaver Loppenstedt, some rights reserved. + * @copyright 2013-2017 Xaver Loppenstedt, some rights reserved. * @license http://spdx.org/licenses/MIT MIT License * @link https://github.com/Mayflower/mo4-coding-standard */ -namespace MO4\Tests\Formatting; - -use PHP_CodeSniffer\Exceptions\RuntimeException; -use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; - -class ArrayAlignmentUnitTest extends AbstractSniffUnitTest +class ArrayDoubleArrowAlignmentUnitTest extends AbstractSniffUnitTest { @@ -49,9 +49,9 @@ class ArrayAlignmentUnitTest extends AbstractSniffUnitTest protected function getErrorList($testFile='') { switch ($testFile) { - case 'ArrayAlignmentUnitTest.pass.inc': + case 'ArrayDoubleArrowAlignmentUnitTest.pass.inc': return array(); - case 'ArrayAlignmentUnitTest.fail.inc': + case 'ArrayDoubleArrowAlignmentUnitTest.fail.inc': return array( 5 => 1, 10 => 1, @@ -82,9 +82,6 @@ protected function getErrorList($testFile='') 132 => 1, 134 => 1, 136 => 2, - 145 => 1, - 151 => 2, - 155 => 1, ); }//end switch diff --git a/MO4/Tests/Arrays/MultiLineArrayUnitTest.fail.inc b/MO4/Tests/Arrays/MultiLineArrayUnitTest.fail.inc new file mode 100644 index 00000000..b80dabff --- /dev/null +++ b/MO4/Tests/Arrays/MultiLineArrayUnitTest.fail.inc @@ -0,0 +1,33 @@ + [ + 'object_id' => 1, + 'object_class' => 'Test', + 'object_class_name' => 'TestClass', + 'object_name' => 'TestObject', + 'id' => 'Test:1',], + 'Test:2' => [ + 'object_id' => 2, + 'object_class' => 'Test', + 'object_class_name' => 'TestClass', + 'object_name' => 'TestObject', + 'id' => 'Test:2',],]; + + +$fail = array( + 1); + +$fail = array(1, + 2, +); + +$fail = [ 1, +2, +]; + +$fail = array( // fail +); diff --git a/MO4/Tests/Arrays/MultiLineArrayUnitTest.fail.inc.fixed b/MO4/Tests/Arrays/MultiLineArrayUnitTest.fail.inc.fixed new file mode 100644 index 00000000..f199c9ba --- /dev/null +++ b/MO4/Tests/Arrays/MultiLineArrayUnitTest.fail.inc.fixed @@ -0,0 +1,41 @@ + [ + 'object_id' => 1, + 'object_class' => 'Test', + 'object_class_name' => 'TestClass', + 'object_name' => 'TestObject', + 'id' => 'Test:1', +], + 'Test:2' => [ + 'object_id' => 2, + 'object_class' => 'Test', + 'object_class_name' => 'TestClass', + 'object_name' => 'TestObject', + 'id' => 'Test:2', +], +]; + + +$fail = array( + 1 +); + +$fail = array( +1, + 2, +); + +$fail = [ + 1, +2, +]; + +$fail = array( + // fail +); diff --git a/MO4/Tests/Arrays/MultiLineArrayUnitTest.pass.inc b/MO4/Tests/Arrays/MultiLineArrayUnitTest.pass.inc new file mode 100644 index 00000000..87691da6 --- /dev/null +++ b/MO4/Tests/Arrays/MultiLineArrayUnitTest.pass.inc @@ -0,0 +1,26 @@ + + * @license http://spdx.org/licenses/MIT MIT License + * @version GIT: master + * @link https://github.com/Mayflower/mo4-coding-standard + */ + +namespace MO4\Tests\Arrays; + +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for @see MultiLineArraySniff + * + * A sniff unit test checks a .inc file for expected violations of a single + * coding standard. Expected errors and warnings are stored in this class. + * + * @category PHP + * @package PHP_CodeSniffer-MO4 + * @author Xaver Loppenstedt + * @copyright 2013-2017 Xaver Loppenstedt, some rights reserved. + * @license http://spdx.org/licenses/MIT MIT License + * @link https://github.com/Mayflower/mo4-coding-standard + */ +class MultiLineArrayUnitTest extends AbstractSniffUnitTest +{ + + + /** + * 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. + * + * @param string $testFile test file + * + * @return array + * @throws RuntimeException + */ + protected function getErrorList($testFile='') + { + switch ($testFile) { + case 'MultiLineArrayUnitTest.pass.inc': + return array(); + case 'MultiLineArrayUnitTest.fail.inc': + return array( + 4 => 1, + 12 => 1, + 18 => 2, + 22 => 1, + 24 => 1, + 28 => 1, + 32 => 1, + ); + }//end switch + + throw new RuntimeException("Testfile {$testFile} in ".__DIR__." is not handled by ".__CLASS__); + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + protected function getWarningList() + { + return array(); + + }//end getWarningList() + + +}//end class diff --git a/README.md b/README.md index a9481ae7..1feaedb6 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,9 @@ Provides a PHP CodeSniffer ruleset for the MO4 coding standard The MO4 Coding Standard is an extension of the [Symfony Coding Standard](http://symfony.com/doc/current/contributing/code/standards.html) and adds following rules: * short array syntax `[...]` must be used instead of `array(...)` +* in multi line arrays, the opening bracket must be followed by newline +* in multi line arrays, the closing bracket must be in own line +* in multi line arrays, the elements must be indented * in associative arrays, the `=>` operators must be aligned * in arrays, the key and `=>` operator must be on the same line * each consecutive variable assignment must align at the assignment operator