Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP 8.3 | Tokenizer/PHP: support "yield from" with comments #647

Merged
merged 8 commits into from
Nov 2, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public function process(File $phpcsFile, $stackPtr)
T_COMMENT => true,
T_END_HEREDOC => true,
T_END_NOWDOC => true,
T_YIELD_FROM => true,
];

for ($i = 0; $i < $phpcsFile->numTokens; $i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,42 +80,57 @@ public function process(File $phpcsFile, $stackPtr)
if ($tokens[$stackPtr]['code'] === T_YIELD_FROM
&& strtolower($content) !== 'yield from'
) {
if ($tokens[($stackPtr - 1)]['code'] === T_YIELD_FROM) {
// A multi-line statement that has already been processed.
return;
}
$found = $content;
$hasComment = false;
$yieldFromEnd = $stackPtr;

// Handle potentially multi-line/multi-token "yield from" expressions.
if (preg_match('`yield\s+from`i', $content) !== 1) {
for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) {
if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false
&& $tokens[$i]['code'] !== T_YIELD_FROM
) {
break;
}

if (isset(Tokens::$commentTokens[$tokens[$i]['code']]) === true) {
$hasComment = true;
}

$found = $content;
if ($tokens[($stackPtr + 1)]['code'] === T_YIELD_FROM) {
// This yield from statement is split over multiple lines.
$i = ($stackPtr + 1);
do {
$found .= $tokens[$i]['content'];
$i++;
} while ($tokens[$i]['code'] === T_YIELD_FROM);
}

if ($tokens[$i]['code'] === T_YIELD_FROM
&& strtolower(trim($tokens[$i]['content'])) === 'from'
) {
break;
}
}

$yieldFromEnd = $i;
}//end if

$error = 'Language constructs must be followed by a single space; expected 1 space between YIELD FROM found "%s"';
$data = [Common::prepareForOutput($found)];
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'IncorrectYieldFrom', $data);
if ($fix === true) {
preg_match('/yield/i', $found, $yield);
preg_match('/from/i', $found, $from);
$phpcsFile->fixer->beginChangeset();
$phpcsFile->fixer->replaceToken($stackPtr, $yield[0].' '.$from[0]);

if ($tokens[($stackPtr + 1)]['code'] === T_YIELD_FROM) {
$i = ($stackPtr + 1);
do {

if ($hasComment === true) {
$phpcsFile->addError($error, $stackPtr, 'IncorrectYieldFromWithComment', $data);
} else {
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'IncorrectYieldFrom', $data);
if ($fix === true) {
preg_match('/yield/i', $found, $yield);
preg_match('/from/i', $found, $from);
$phpcsFile->fixer->beginChangeset();
$phpcsFile->fixer->replaceToken($stackPtr, $yield[0].' '.$from[0]);

for ($i = ($stackPtr + 1); $i <= $yieldFromEnd; $i++) {
$phpcsFile->fixer->replaceToken($i, '');
$i++;
} while ($tokens[$i]['code'] === T_YIELD_FROM);
}
}

$phpcsFile->fixer->endChangeset();
}
$phpcsFile->fixer->endChangeset();
}
}//end if

return;
return ($yieldFromEnd + 1);
}//end if

if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) {
Expand Down
7 changes: 7 additions & 0 deletions src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,12 @@ if (ISSET($a) && !Empty($a)) { UnSeT($a); }
eval('foo');
eVaL('foo');

$c = function() {
Yield /*comment*/ From fun();
YIELD
/*comment*/
FROM fun();
}

__HALT_COMPILER(); // An exception due to phar support.
function
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,12 @@ if (isset($a) && !empty($a)) { unset($a); }
eval('foo');
eval('foo');

$c = function() {
yield /*comment*/ from fun();
yield
/*comment*/
from fun();
}

__HALT_COMPILER(); // An exception due to phar support.
function
3 changes: 3 additions & 0 deletions src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ public function getErrorList()
48 => 1,
52 => 3,
54 => 1,
57 => 2,
58 => 1,
60 => 1,
];

}//end getErrorList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,10 @@ $x = 1;

Another line.
*/

// A `yield from` can be multiline and may contain spaces in the indentation whitespace between the keywords.
function myGenerator() {
yield
from
gen2();
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,10 @@ $x = 1;

Another line.
*/

// A `yield from` can be multiline and may contain spaces in the indentation whitespace between the keywords.
function myGenerator() {
yield
from
gen2();
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,10 @@ $x = 1;

Another line.
*/

// A `yield from` can be multiline and may contain spaces in the indentation whitespace between the keywords.
function myGenerator() {
yield
from
gen2();
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,10 @@ $x = 1;

Another line.
*/

// A `yield from` can be multiline and may contain spaces in the indentation whitespace between the keywords.
function myGenerator() {
yield
from
gen2();
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public function getErrorList($testFile='')
115 => 1,
117 => 1,
118 => 1,
123 => 1,
];

case 'DisallowSpaceIndentUnitTest.3.inc':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,12 @@ $var = "$hello $there";

Another line.
*/

// A `yield from` can be single-line and multiline and may contain a tab in the whitespace between the keywords.
function myGenerator() {
yield from gen1();

yield
from
gen2();
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,12 @@ $var = "$hello $there";

Another line.
*/

// A `yield from` can be single-line and multiline and may contain a tab in the whitespace between the keywords.
function myGenerator() {
yield from gen1();

yield
from
gen2();
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,43 +50,45 @@ public function getErrorList($testFile='')
switch ($testFile) {
case 'DisallowTabIndentUnitTest.1.inc':
return [
5 => 2,
9 => 1,
15 => 1,
20 => 2,
21 => 1,
22 => 2,
23 => 1,
24 => 2,
31 => 1,
32 => 2,
33 => 2,
41 => 1,
42 => 1,
43 => 1,
44 => 1,
45 => 1,
46 => 1,
47 => 1,
48 => 1,
54 => 1,
55 => 1,
56 => 1,
57 => 1,
58 => 1,
59 => 1,
79 => 1,
80 => 1,
81 => 1,
82 => 1,
83 => 1,
85 => 1,
86 => 1,
87 => 1,
89 => 1,
90 => 1,
92 => 1,
93 => 1,
5 => 2,
9 => 1,
15 => 1,
20 => 2,
21 => 1,
22 => 2,
23 => 1,
24 => 2,
31 => 1,
32 => 2,
33 => 2,
41 => 1,
42 => 1,
43 => 1,
44 => 1,
45 => 1,
46 => 1,
47 => 1,
48 => 1,
54 => 1,
55 => 1,
56 => 1,
57 => 1,
58 => 1,
59 => 1,
79 => 1,
80 => 1,
81 => 1,
82 => 1,
83 => 1,
85 => 1,
86 => 1,
87 => 1,
89 => 1,
90 => 1,
92 => 1,
93 => 1,
97 => 1,
100 => 1,
];

case 'DisallowTabIndentUnitTest.2.inc':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,12 @@ $newLine;
// The following line must have a single space at the end (after return)
return
$spaceAndNewLine;

// Related to issue #529. These should not be auto-fixed as we don't know what to do with the comment.
yield /*comment*/ from $test();
yield
# comment
from $test();
yield
// phpcs:ignore Stnd.Category.SniffName
from $test();
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,12 @@ return $newLine;

// The following line must have a single space at the end (after return)
return $spaceAndNewLine;

// Related to issue #529. These should not be auto-fixed as we don't know what to do with the comment.
yield /*comment*/ from $test();
yield
# comment
from $test();
yield
// phpcs:ignore Stnd.Category.SniffName
from $test();
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ public function getErrorList($testFile='')
85 => 1,
86 => 1,
90 => 1,
94 => 1,
95 => 1,
98 => 1,
];

default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1614,6 +1614,12 @@ match (true) {
]
};

// Issue squizlabs/PHP_CodeSniffer#3808
function test() {
yield
from [ 3, 4 ];
}

/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */
?>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1614,6 +1614,12 @@ match (true) {
]
};

// Issue squizlabs/PHP_CodeSniffer#3808
function test() {
yield
from [ 3, 4 ];
}

/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */
?>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1614,6 +1614,12 @@ match (true) {
]
};

// Issue squizlabs/PHP_CodeSniffer#3808
function test() {
yield
from [ 3, 4 ];
}

/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */
?>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1614,6 +1614,12 @@ match (true) {
]
};

// Issue squizlabs/PHP_CodeSniffer#3808
function test() {
yield
from [ 3, 4 ];
}

/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */
?>

Expand Down
10 changes: 8 additions & 2 deletions src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false
phpcs:set Generic.WhiteSpace.ScopeIndent exact true
<?php
// phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false
// phpcs:set Generic.WhiteSpace.ScopeIndent exact true
function test()
{
echo 'test';
Expand All @@ -26,3 +26,9 @@ if ($foo) {
$this->foo()
->bar()
->baz();

// Issue squizlabs/PHP_CodeSniffer#3808
function test() {
yield
from [ 3, 4 ];
}
Loading