diff --git a/Universal/Sniffs/WhiteSpace/DisallowInlineTabsSniff.php b/Universal/Sniffs/WhiteSpace/DisallowInlineTabsSniff.php index 817a44e1..77d15d00 100644 --- a/Universal/Sniffs/WhiteSpace/DisallowInlineTabsSniff.php +++ b/Universal/Sniffs/WhiteSpace/DisallowInlineTabsSniff.php @@ -63,6 +63,9 @@ final class DisallowInlineTabsSniff implements Sniff \T_DOC_COMMENT_WHITESPACE => true, \T_DOC_COMMENT_STRING => true, \T_COMMENT => true, + \T_START_HEREDOC => true, + \T_START_NOWDOC => true, + \T_YIELD_FROM => true, ]; /** @@ -102,7 +105,7 @@ public function process(File $phpcsFile, $stackPtr) $dummy = new DummyTokenizer('', $phpcsFile->config); for ($i = 0; $i < $phpcsFile->numTokens; $i++) { - // Skip all non-whitespace tokens and skip whitespace at the start of a new line. + // Skip all non-target tokens and skip whitespace at the start of a new line. if (isset($this->find[$tokens[$i]['code']]) === false || (($tokens[$i]['code'] === \T_WHITESPACE || $tokens[$i]['code'] === \T_DOC_COMMENT_WHITESPACE) @@ -147,6 +150,16 @@ public function process(File $phpcsFile, $stackPtr) } } + /* + * For "yield from", we should only handle tabs _between_ the keywords (single token), + * not indentation for those situations where the keyword is split in multiple tokens. + */ + if ($tokens[$i]['code'] === \T_YIELD_FROM + && \preg_match('`^yield.+from$`i', $tokens[$i]['content']) !== 1 + ) { + continue; + } + $fix = $phpcsFile->addFixableError( 'Spaces must be used for mid-line alignment; tabs are not allowed', $i, diff --git a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.1.inc b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.1.inc index 0d065c08..f50b2102 100644 --- a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.1.inc +++ b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.1.inc @@ -59,3 +59,24 @@ $aaaaaaaa = true; // Tab indented, no tabs. // phpcs:ignore Stnd.Cat.SniffName -- testing mixed comment + annotations don't trigger on indentation. // Tab indented, no tabs. + +$a = <<< TAB_BETWEEN +text +TAB_BETWEEN; + +$a = <<< 'TABS_BETWEEN' +text +TABS_BETWEEN; + +function myGenerator() { + yield from tabsBetweenShouldBeFixed(); + +yield /*comment*/ from tabsBetweenShouldBeFixedEvenWhenKeywordStartsOnColumn1(); + + yield + from tabIndentationShouldBeIgnored(); + + yield + /*comment*/ + from tabIndentationShouldBeIgnored(); +} diff --git a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.1.inc.fixed b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.1.inc.fixed index 63726813..37c19527 100644 --- a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.1.inc.fixed +++ b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.1.inc.fixed @@ -59,3 +59,24 @@ $aaaaaaaa = true; // Tab indented, no tabs. // phpcs:ignore Stnd.Cat.SniffName -- testing mixed comment + annotations don't trigger on indentation. // Tab indented, no tabs. + +$a = <<< TAB_BETWEEN +text +TAB_BETWEEN; + +$a = <<< 'TABS_BETWEEN' +text +TABS_BETWEEN; + +function myGenerator() { + yield from tabsBetweenShouldBeFixed(); + +yield /*comment*/ from tabsBetweenShouldBeFixedEvenWhenKeywordStartsOnColumn1(); + + yield + from tabIndentationShouldBeIgnored(); + + yield + /*comment*/ + from tabIndentationShouldBeIgnored(); +} diff --git a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.4.inc b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.4.inc index 7227c96c..d79d8d3f 100644 --- a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.4.inc +++ b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.4.inc @@ -33,3 +33,17 @@ $aaaaaaaa = true; // Tab indented and inline tabs. // Tab indented and inline tabs. + +$a = <<< TAB_BETWEEN +text +TAB_BETWEEN; + +$a = <<< 'TABS_BETWEEN' +text +TABS_BETWEEN; + +function myGenerator() { + yield from tabsBetweenShouldBeFixed(); + +yield /*comment*/ from tabsBetweenShouldBeFixedEvenWhenKeywordStartsOnColumn1(); +} diff --git a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.4.inc.fixed b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.4.inc.fixed index 982e48ea..715f13e0 100644 --- a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.4.inc.fixed +++ b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.4.inc.fixed @@ -33,3 +33,17 @@ $aaaaaaaa = true; // Tab indented and inline tabs. // Tab indented and inline tabs. + +$a = <<< TAB_BETWEEN +text +TAB_BETWEEN; + +$a = <<< 'TABS_BETWEEN' +text +TABS_BETWEEN; + +function myGenerator() { + yield from tabsBetweenShouldBeFixed(); + +yield /*comment*/ from tabsBetweenShouldBeFixedEvenWhenKeywordStartsOnColumn1(); +} diff --git a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.5.inc b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.5.inc index 139b27fd..1904a508 100644 --- a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.5.inc +++ b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.5.inc @@ -33,3 +33,17 @@ $aaaaaaaa = true; // Tab indented and inline tabs. // Tab indented and inline tabs. + +$a = <<< TAB_BETWEEN +text +TAB_BETWEEN; + +$a = <<< 'TABS_BETWEEN' +text +TABS_BETWEEN; + +function myGenerator() { + yield from tabsBetweenShouldBeFixed(); + +yield /*comment*/ from tabsBetweenShouldBeFixedEvenWhenKeywordStartsOnColumn1(); +} diff --git a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.5.inc.fixed b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.5.inc.fixed index ce001601..e2bd84e0 100644 --- a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.5.inc.fixed +++ b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.5.inc.fixed @@ -33,3 +33,17 @@ $aaaaaaaa = true; // Tab indented and inline tabs. // Tab indented and inline tabs. + +$a = <<< TAB_BETWEEN +text +TAB_BETWEEN; + +$a = <<< 'TABS_BETWEEN' +text +TABS_BETWEEN; + +function myGenerator() { + yield from tabsBetweenShouldBeFixed(); + +yield /*comment*/ from tabsBetweenShouldBeFixedEvenWhenKeywordStartsOnColumn1(); +} diff --git a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.6.inc b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.6.inc index 05b55208..9dcecd1b 100644 --- a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.6.inc +++ b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.6.inc @@ -41,3 +41,24 @@ $aaaaaaaa = true; * @param int $var Description. * @param string $string Another description. */ + +$a = <<< TAB_BETWEEN +text +TAB_BETWEEN; + +$a = <<< 'TABS_BETWEEN' +text +TABS_BETWEEN; + +function myGenerator() { + yield from tabsBetweenShouldBeFixed(); + + yield /*comment*/ from tabsBetweenShouldBeFixed(); + + yield + from tabIndentationShouldBeIgnored(); + + yield + /*comment*/ + from tabIndentationShouldBeIgnored(); +} diff --git a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.php b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.php index 147e3361..4de61162 100644 --- a/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.php +++ b/Universal/Tests/WhiteSpace/DisallowInlineTabsUnitTest.php @@ -10,6 +10,7 @@ namespace PHPCSExtra\Universal\Tests\WhiteSpace; +use PHP_CodeSniffer\Config; use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; /** @@ -73,6 +74,12 @@ public function setCliValues($testFile, $config) */ public function getErrorList($testFile = '') { + // As of PHP 8.3, comments may be tokenized within a "yield from" token, but only for PHPCS < 3.11.0. + $commentsInYieldFrom = false; + if (\PHP_VERSION_ID >= 80300 && \version_compare(Config::VERSION, '3.11.0', '<')) { + $commentsInYieldFrom = true; + } + switch ($testFile) { case 'DisallowInlineTabsUnitTest.1.inc': return [ @@ -93,6 +100,10 @@ public function getErrorList($testFile = '') 49 => 1, 52 => 1, 53 => 1, + 63 => 1, + 67 => 1, + 72 => 1, + 74 => ($commentsInYieldFrom === true ? 1 : 2), ]; case 'DisallowInlineTabsUnitTest.2.inc': @@ -126,6 +137,10 @@ public function getErrorList($testFile = '') 31 => 1, 34 => 1, 35 => 1, + 37 => 1, + 41 => 1, + 46 => 1, + 48 => ($commentsInYieldFrom === true ? 1 : 2), ]; case 'DisallowInlineTabsUnitTest.5.inc': @@ -145,6 +160,10 @@ public function getErrorList($testFile = '') 31 => 1, 34 => 1, 35 => 1, + 37 => 1, + 41 => 1, + 46 => 1, + 48 => ($commentsInYieldFrom === true ? 1 : 2), ]; default: