Skip to content

Commit 6457a5a

Browse files
committed
Generic/UnnecessaryHeredoc: bug fix - false positives for heredoc with escape sequence
If the original heredoc contained an escape sequence, but no variable interpolation or expressions, it would be flagged as unnecessary and fixed to nowdoc, even though escape sequences are not supported in nowdocs. Fixed now. Includes tests.
1 parent 7f4fdc7 commit 6457a5a

File tree

5 files changed

+92
-0
lines changed

5 files changed

+92
-0
lines changed

src/Standards/Generic/Sniffs/Strings/UnnecessaryHeredocSniff.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,35 @@
1515
class UnnecessaryHeredocSniff implements Sniff
1616
{
1717

18+
/**
19+
* Escape chars which are supported in heredocs, but not in nowdocs.
20+
*
21+
* @var array<string>
22+
*/
23+
private $escapeChars = [
24+
// Octal sequences.
25+
'\0',
26+
'\1',
27+
'\2',
28+
'\3',
29+
'\4',
30+
'\5',
31+
'\6',
32+
'\7',
33+
34+
// Various whitespace and the escape char.
35+
'\n',
36+
'\r',
37+
'\t',
38+
'\v',
39+
'\e',
40+
'\f',
41+
42+
// Hex and unicode sequences.
43+
'\x',
44+
'\u',
45+
];
46+
1847

1948
/**
2049
* Returns an array of tokens this test wants to listen for.
@@ -81,6 +110,13 @@ public function process(File $phpcsFile, $stackPtr)
81110

82111
$phpcsFile->recordMetric($stackPtr, 'Heredoc contains interpolation or expression', 'no');
83112

113+
// Check for escape sequences which aren't supported in nowdocs.
114+
foreach ($this->escapeChars as $testChar) {
115+
if (strpos($body, $testChar) !== false) {
116+
return;
117+
}
118+
}
119+
84120
$warning = 'Detected heredoc without interpolation or expressions. Use nowdoc syntax instead';
85121

86122
$fix = $phpcsFile->addFixableWarning($warning, $stackPtr, 'Found');

src/Standards/Generic/Tests/Strings/UnnecessaryHeredocUnitTest.1.inc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,17 @@ some text
106106
some \$text
107107
some text \\ including a backslash
108108
END;
109+
110+
$heredoc = <<<EOD
111+
<?php
112+
echo 'The below line contains escape characters and should be recognized as needing heredoc';
113+
echo "aa\xC3\xC3 \xC3\xB8aa";
114+
EOD;
115+
116+
echo <<<EOT
117+
This should print a capital 'A': \x41
118+
EOT;
119+
120+
echo <<<EOT
121+
Here we should have a tab and 2 'A's: \t \101 \u{41}
122+
EOT;

src/Standards/Generic/Tests/Strings/UnnecessaryHeredocUnitTest.1.inc.fixed

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,17 @@ some text
106106
some $text
107107
some text \ including a backslash
108108
END;
109+
110+
$heredoc = <<<EOD
111+
<?php
112+
echo 'The below line contains escape characters and should be recognized as needing heredoc';
113+
echo "aa\xC3\xC3 \xC3\xB8aa";
114+
EOD;
115+
116+
echo <<<EOT
117+
This should print a capital 'A': \x41
118+
EOT;
119+
120+
echo <<<EOT
121+
Here we should have a tab and 2 'A's: \t \101 \u{41}
122+
EOT;

src/Standards/Generic/Tests/Strings/UnnecessaryHeredocUnitTest.2.inc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,17 @@ $heredoc = <<< "END"
106106
some \$text
107107
some text \\ including a backslash
108108
END;
109+
110+
$heredoc = <<<EOD
111+
<?php
112+
echo 'The below line contains escape characters and should be recognized as needing heredoc';
113+
echo "aa\xC3\xC3 \xC3\xB8aa";
114+
EOD;
115+
116+
echo <<<EOT
117+
This should print a capital 'A': \x41
118+
EOT;
119+
120+
echo <<<EOT
121+
Here we should have a tab and 2 'A's: \t \101 \u{41}
122+
EOT;

src/Standards/Generic/Tests/Strings/UnnecessaryHeredocUnitTest.2.inc.fixed

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,17 @@ $heredoc = <<< 'END'
106106
some $text
107107
some text \ including a backslash
108108
END;
109+
110+
$heredoc = <<<EOD
111+
<?php
112+
echo 'The below line contains escape characters and should be recognized as needing heredoc';
113+
echo "aa\xC3\xC3 \xC3\xB8aa";
114+
EOD;
115+
116+
echo <<<EOT
117+
This should print a capital 'A': \x41
118+
EOT;
119+
120+
echo <<<EOT
121+
Here we should have a tab and 2 'A's: \t \101 \u{41}
122+
EOT;

0 commit comments

Comments
 (0)