From 27714f58cf3333ebe8686484dab2604e74668044 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Fri, 5 Jul 2024 02:31:30 +0200 Subject: [PATCH] Generic/DisallowSpaceIndent: flag heredoc/nowdoc closer using tab indent This is the same fix for the `Generic.WhiteSpace.DisallowSpaceIndent` sniff as was previously made in squizlabs/PHP_CodeSniffer 3640 and 533 for the sister-sniff `Generic.WhiteSpace.DisallowTabIndent`. --- Since PHP 7.3, heredoc/nowdoc closers may be indented. This indent can use either tabs or spaces and the indent is included in the `T_END_HEREDOC`/`T_END_NOWDOC` token contents as received from the PHP native tokenizer. However, these tokens were not included in the tokens to look at for the `Generic.WhiteSpace.DisallowSpaceIndent` sniff, which could lead to false negatives. Fixed now, includes tests. And along the same lines as per 533: * The error for space indentation of heredoc/nowdoc closers is not auto-fixable to prevent the fixer creating parse errors as the indentation of the _contents_ of the heredoc/nowdoc has to be the same as for the closer. * The error for space indentation of heredoc/nowdoc closers has its own error code to allow for selectively ignoring the indentation of heredoc/nowdoc closers. --- .../WhiteSpace/DisallowSpaceIndentSniff.php | 16 ++++++++++++++-- .../WhiteSpace/DisallowSpaceIndentUnitTest.4.inc | 13 +++++++++++++ .../WhiteSpace/DisallowSpaceIndentUnitTest.php | 11 +++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.4.inc diff --git a/src/Standards/Generic/Sniffs/WhiteSpace/DisallowSpaceIndentSniff.php b/src/Standards/Generic/Sniffs/WhiteSpace/DisallowSpaceIndentSniff.php index ca2daafcac..37edfc887a 100644 --- a/src/Standards/Generic/Sniffs/WhiteSpace/DisallowSpaceIndentSniff.php +++ b/src/Standards/Generic/Sniffs/WhiteSpace/DisallowSpaceIndentSniff.php @@ -78,6 +78,8 @@ public function process(File $phpcsFile, $stackPtr) T_INLINE_HTML => true, T_DOC_COMMENT_WHITESPACE => true, T_COMMENT => true, + T_END_HEREDOC => true, + T_END_NOWDOC => true, ]; $eolLen = strlen($phpcsFile->eolChar); @@ -202,8 +204,18 @@ public function process(File $phpcsFile, $stackPtr) } }//end if - $error = 'Tabs must be used to indent lines; spaces are not allowed'; - $fix = $phpcsFile->addFixableError($error, $i, 'SpacesUsed'); + $error = 'Tabs must be used to indent lines; spaces are not allowed'; + $errorCode = 'SpacesUsed'; + + // Report, but don't auto-fix space identation for a PHP 7.3+ flexible heredoc/nowdoc closer. + // Auto-fixing this would cause parse errors as the indentation of the heredoc/nowdoc contents + // needs to use the same type of indentation. Also see: https://3v4l.org/7OF3M . + if ($tokens[$i]['code'] === T_END_HEREDOC || $tokens[$i]['code'] === T_END_NOWDOC) { + $phpcsFile->addError($error, $i, $errorCode.'HeredocCloser'); + continue; + } + + $fix = $phpcsFile->addFixableError($error, $i, $errorCode); if ($fix === true) { $padding = str_repeat("\t", $expectedTabs); $padding .= str_repeat(' ', $expectedSpaces); diff --git a/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.4.inc b/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.4.inc new file mode 100644 index 0000000000..b438a9d8c1 --- /dev/null +++ b/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.4.inc @@ -0,0 +1,13 @@ + 1, ]; + case 'DisallowSpaceIndentUnitTest.4.inc': + if (PHP_VERSION_ID >= 70300) { + return [ + 7 => 1, + 13 => 1, + ]; + } + + // PHP 7.2 or lower: PHP version which doesn't support flexible heredocs/nowdocs yet. + return []; + case 'DisallowSpaceIndentUnitTest.js': return [3 => 1];