diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e81672..bb5ade4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [8.0.0] - ### Added -- Add MO4.WhiteSpace.ConstantSpacing +- Add `MO4.WhiteSpace.ConstantSpacing` +- Add `MO4.WhiteSpace.MultipleEmptyLinesSniff` ### Changed - refactored tests diff --git a/MO4/Sniffs/WhiteSpace/MultipleEmptyLinesSniff.php b/MO4/Sniffs/WhiteSpace/MultipleEmptyLinesSniff.php new file mode 100644 index 0000000..e52853c --- /dev/null +++ b/MO4/Sniffs/WhiteSpace/MultipleEmptyLinesSniff.php @@ -0,0 +1,97 @@ + + * + * @see Tokens.php + */ + public function register(): array + { + return [ + // Assume most comments end with a newline + T_COMMENT, + // Assume all getTokens(); + + // This sniff intentionally doesn't care about whitespace at the end of the file + if (!isset($tokens[$stackPtr + 3]) + || $tokens[$stackPtr + 2]['line'] === $tokens[$stackPtr + 3]['line'] + ) { + return $stackPtr + 3; + } + + if ($tokens[$stackPtr + 1]['line'] === $tokens[$stackPtr + 2]['line']) { + return $stackPtr + 2; + } + + // Finally, check the assumption the current token is or ends with a newline + if ($tokens[$stackPtr]['line'] === $tokens[$stackPtr + 1]['line']) { + return; + } + + // Search for the next non-newline token + $next = $stackPtr + 1; + + while (isset($tokens[$next + 1]) && + $tokens[$next]['code'] === T_WHITESPACE && + $tokens[$next]['line'] !== $tokens[$next + 1]['line'] + ) { + $next++; + } + + $count = $next - $stackPtr - 1; + + if ($count > 1 + && $phpcsFile->addFixableError( + 'Multiple empty lines should not exist in a row; found %s consecutive empty lines', + $stackPtr + 1, + 'MultipleEmptyLines', + [$count] + ) + ) { + $phpcsFile->fixer->beginChangeset(); + + // Remove all newlines except the first two, i.e. keep one empty line + for ($i = $stackPtr + 2; $i < $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + // Don't check the current sequence a second time + return $next; + } +} diff --git a/MO4/Tests/WhiteSpace/MultipleEmptyLinesUnitTest.fail.inc b/MO4/Tests/WhiteSpace/MultipleEmptyLinesUnitTest.fail.inc new file mode 100644 index 0000000..0fd5db0 --- /dev/null +++ b/MO4/Tests/WhiteSpace/MultipleEmptyLinesUnitTest.fail.inc @@ -0,0 +1,48 @@ + + * + * @license http://spdx.org/licenses/MIT MIT License + * + * @link https://github.com/mayflower/mo4-coding-standard + */ + +declare(strict_types=1); + +namespace MO4\Tests\WhiteSpace; + +use MO4\Tests\AbstractMo4SniffUnitTest; + +/** + * Unit test class for the MultipleEmptyLines sniff. + * + * A sniff unit test checks a .inc file for expected violations of a single + * coding standard. Expected errors and warnings are stored in this class. + * + * @author Xaver Loppenstedt + * + * @copyright 2013 Xaver Loppenstedt, some rights reserved. + * + * @license http://spdx.org/licenses/MIT MIT License + * + * @link https://github.com/mayflower/mo4-coding-standard + */ +class MultipleEmptyLinesUnitTest extends AbstractMo4SniffUnitTest +{ + protected $expectedErrorList = [ + 'MultipleEmptyLinesUnitTest.pass.inc' => [], + 'MultipleEmptyLinesUnitTest.fail.inc' => [ + 2 => 1, + 14 => 1, + 21 => 1, + 24 => 1, + 29 => 1, + ], + ]; +} diff --git a/README.md b/README.md index 1045b8b..93580c9 100644 --- a/README.md +++ b/README.md @@ -77,10 +77,12 @@ To change the sorting order for your project, add this snippet to your custom `r ### MO4.Strings.VariableInDoubleQuotedString * Interpolated variables in double quoted strings must be surrounded by `{ }`, e.g. `{$VAR}` instead of `$VAR`. -## MO4.WhiteSpace.ConstantSpacing - +### MO4.WhiteSpace.ConstantSpacing * const must be followed by a single space. +### MO4.WhiteSpace.MultipleEmptyLines +* No more than one empty consecutive line is allowed. Taken from [mediawiki/mediawiki-codesniffer](https://github.com/wikimedia/mediawiki-tools-codesniffer). + ### Further rules (imported from other standards) * See `MO4/ruleset.xml`, which has each imported rule commented.