-
-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #508 from PHPCSStandards/feature/tokenizer-php-har…
…den-the-dnf-layer-some-more Tokenizer/PHP: add extra hardening to the (DNF) type handling + efficiency improvement
- Loading branch information
Showing
5 changed files
with
379 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?php | ||
|
||
// Parentheses in broken DNF type declarations will remain tokenized as normal parentheses. | ||
// This test is in a separate file as the 'nested_parenthesis' indexes will be off after this code. | ||
class ParseErrors { | ||
/* testBrokenConstDNFTypeEndOnOpenParenthesis */ | ||
const A|(B PARSE_ERROR = null; | ||
|
||
/* testBrokenPropertyDNFTypeEndOnOpenParenthesis */ | ||
public A|(B $parseError; | ||
|
||
function unmatchedParens { | ||
/* testBrokenParamDNFTypeEndOnOpenParenthesis */ | ||
A|(B $parseError, | ||
/* testBrokenReturnDNFTypeEndOnOpenParenthesis */ | ||
) : A|(B {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<?php | ||
/** | ||
* Tests that parentheses tokens are not converted to type parentheses tokens in broken DNF types. | ||
* | ||
* @author Juliette Reinders Folmer <phpcs_nospam@adviesenzo.nl> | ||
* @copyright 2024 PHPCSStandards and contributors | ||
* @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence | ||
*/ | ||
|
||
namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; | ||
|
||
use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; | ||
|
||
final class DNFTypesParseError1Test extends AbstractTokenizerTestCase | ||
{ | ||
|
||
|
||
/** | ||
* Document handling for a DNF type / parse error where the last significant type specific token is an open parenthesis. | ||
* | ||
* @param string $testMarker The comment prefacing the target token. | ||
* | ||
* @dataProvider dataBrokenDNFTypeCantEndOnOpenParenthesis | ||
* @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional | ||
* | ||
* @return void | ||
*/ | ||
public function testBrokenDNFTypeCantEndOnOpenParenthesis($testMarker) | ||
{ | ||
$tokens = $this->phpcsFile->getTokens(); | ||
|
||
$openPtr = $this->getTargetToken($testMarker, [T_OPEN_PARENTHESIS, T_TYPE_OPEN_PARENTHESIS], '('); | ||
$token = $tokens[$openPtr]; | ||
|
||
// Verify that the open parenthesis is tokenized as a normal parenthesis. | ||
$this->assertSame(T_OPEN_PARENTHESIS, $token['code'], 'Token tokenized as '.$token['type'].', not T_OPEN_PARENTHESIS (code)'); | ||
$this->assertSame('T_OPEN_PARENTHESIS', $token['type'], 'Token tokenized as '.$token['type'].', not T_OPEN_PARENTHESIS (type)'); | ||
|
||
// Verify that the type union is still tokenized as T_BITWISE_OR as the type declaration | ||
// is not recognized as a valid type declaration. | ||
$unionPtr = $this->getTargetToken($testMarker, [T_BITWISE_OR, T_TYPE_UNION], '|'); | ||
$token = $tokens[$unionPtr]; | ||
|
||
$this->assertSame(T_BITWISE_OR, $token['code'], 'Token tokenized as '.$token['type'].', not T_BITWISE_OR (code)'); | ||
$this->assertSame('T_BITWISE_OR', $token['type'], 'Token tokenized as '.$token['type'].', not T_BITWISE_OR (type)'); | ||
|
||
}//end testBrokenDNFTypeCantEndOnOpenParenthesis() | ||
|
||
|
||
/** | ||
* Data provider. | ||
* | ||
* @see testBrokenDNFTypeCantEndOnOpenParenthesis() | ||
* | ||
* @return array<string, array<string, string>> | ||
*/ | ||
public static function dataBrokenDNFTypeCantEndOnOpenParenthesis() | ||
{ | ||
return [ | ||
'OO const type' => ['/* testBrokenConstDNFTypeEndOnOpenParenthesis */'], | ||
'OO property type' => ['/* testBrokenPropertyDNFTypeEndOnOpenParenthesis */'], | ||
'Parameter type' => ['/* testBrokenParamDNFTypeEndOnOpenParenthesis */'], | ||
'Return type' => ['/* testBrokenReturnDNFTypeEndOnOpenParenthesis */'], | ||
]; | ||
|
||
}//end dataBrokenDNFTypeCantEndOnOpenParenthesis() | ||
|
||
|
||
}//end class |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
|
||
// Parentheses in broken DNF type declarations will remain tokenized as normal parentheses. | ||
// This test is in a separate file as the 'nested_parenthesis' indexes will be off after this code. | ||
// | ||
// Also note that the order of these tests is deliberate to try and trick the parentheses handling | ||
// in the Tokenizer class into matching parentheses pairs, even though the parentheses do | ||
// no belong together. | ||
|
||
class UnmatchedParentheses { | ||
/* testBrokenConstDNFTypeParensMissingClose */ | ||
const A|(B&C PARSE_ERROR_1 = null; | ||
|
||
/* testBrokenConstDNFTypeParensMissingOpen */ | ||
const A|B&C) PARSE_ERROR_2 = null; | ||
|
||
/* testBrokenPropertyDNFTypeParensMissingClose */ | ||
private A|(B&C $parseError1; | ||
|
||
/* testBrokenPropertyDNFTypeParensMissingOpen */ | ||
protected A|B&C) $parseError2; | ||
|
||
function unmatchedParens1 ( | ||
/* testBrokenParamDNFTypeParensMissingClose */ | ||
A|(B&C $parseError, | ||
/* testBrokenReturnDNFTypeParensMissingOpen */ | ||
) : A|B&C) {} | ||
|
||
function unmatchedParens2 ( | ||
/* testBrokenParamDNFTypeParensMissingOpen */ | ||
A|B&C) $parseError | ||
/* testBrokenReturnDNFTypeParensMissingClose */ | ||
) : A|(B&C {} | ||
} | ||
|
||
class MatchedAndUnmatchedParentheses { | ||
/* testBrokenConstDNFTypeParensMissingOneClose */ | ||
const (A&B)|(B&C PARSE_ERROR = null; | ||
|
||
/* testBrokenPropertyDNFTypeParensMissingOneOpen */ | ||
protected (A&B)|B&C) $parseError; | ||
|
||
function unmatchedParens ( | ||
/* testBrokenParamDNFTypeParensMissingOneClose */ | ||
(A&B)|(B&C $parseError, | ||
/* testBrokenReturnDNFTypeParensMissingOneOpen */ | ||
) : (A&B)|B&C) {} | ||
} |
Oops, something went wrong.