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
Bug in attribute tokenization when content contains PHP end token or attribute closer on new line #3294
Comments
I've created a unit test for it, but I'm not sure if this is actually solvable. As, on PHP < 8.0, the This feels like a similar issue to #2055 (PHP 7.3 indented heredoc/nowdoc) were retokenizing the whole file without the problem code and then reinserting the problem code is just not feasible. /* testAttributeContainingTextLookingLikeCloseTag */
#[DeprecationReason('reason: <https://some-website/reason?>')]
function main() {} /**
* Test that an attribute containing text which looks like a PHP close tag is tokenized correctly.
*
* @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute
*
* @return void
*/
public function testAttributeContainingTextLookingLikeCloseTag()
{
$tokens = self::$phpcsFile->getTokens();
$attribute = $this->getTargetToken('/* testAttributeContainingTextLookingLikeCloseTag */', T_ATTRIBUTE);
$this->assertSame('T_ATTRIBUTE', $tokens[$attribute]['type']);
$this->assertArrayHasKey('attribute_closer', $tokens[$attribute]);
$closer = $tokens[$attribute]['attribute_closer'];
$this->assertSame(($attribute + 5), $closer);
$this->assertSame(T_ATTRIBUTE_END, $tokens[$closer]['code']);
$this->assertSame('T_ATTRIBUTE_END', $tokens[$closer]['type']);
$this->assertSame($tokens[$attribute]['attribute_opener'], $tokens[$closer]['attribute_opener']);
$this->assertSame($tokens[$attribute]['attribute_closer'], $tokens[$closer]['attribute_closer']);
$expectedTokensAttribute = [
'T_STRING' => 'DeprecationReason',
'T_OPEN_PARENTHESIS' => '(',
'T_CONSTANT_ENCAPSED_STRING' => "'reason: <https://some-website/reason?>'",
'T_CLOSE_PARENTHESIS' => ')',
'T_ATTRIBUTE_END' => ']',
];
$i = ($attribute + 1);
foreach ($expectedTokensAttribute as $expectedType => $expectedContents) {
$this->assertSame($expectedType, $tokens[$i]['type']);
$this->assertSame($expectedContents, $tokens[$i]['content']);
$this->assertArrayHasKey('attribute_opener', $tokens[$i]);
$this->assertArrayHasKey('attribute_closer', $tokens[$i]);
++$i;
}
$expectedTokensAfter = [
T_WHITESPACE,
T_FUNCTION,
T_WHITESPACE,
T_STRING,
T_OPEN_PARENTHESIS,
T_CLOSE_PARENTHESIS,
T_WHITESPACE,
T_OPEN_CURLY_BRACKET,
T_CLOSE_CURLY_BRACKET,
];
$i = ($closer + 1);
foreach ($expectedTokensAfter as $expectedCode) {
$this->assertSame($expectedCode, $tokens[$i]['code']);
++$i;
}
}//end testAttributeContainingTextLookingLikeCloseTag() |
Hi @jrfnl, |
@alekitto Thanks for the quick response again! I've ran some tests with the fix in place and while I can't guarantee either that it will cover every possible case, it does seem to cover this one well. 👍 I'd suggest pulling the fix. If/when more edge cases would be discovered, those can be dealt with at that point in time. |
Describe the bug
Tokenization of attributes is not always consistent across PHP versions.
While the given code sample may be an edge case, it is 100% valid PHP 8.0 code and is in actual fact one of the examples given in one of the related RFCs.
(last example in this section: https://wiki.php.net/rfc/shorter_attribute_syntax_change#discussion_of_forwards_compatibility_procons )
Code sample
Tokenizes on PHP 8.0 with PHPCS 3.6.0 as:
... while on PHP <8.0, like PHP 7.4 or PHP 5.6, with PHPCS 3.6.0, it tokenizes as:
Expected behavior
Consistent tokenization of code across PHP version.
Versions (please complete the following information):
Additional context
Related to PR #3203 /cc @alekitto (sorry, I didn't get round to doing edge case testing before)
The text was updated successfully, but these errors were encountered: