diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 9185cd41b0..54be7ba686 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -139,7 +139,7 @@ - tests/Core/Tokenizer/StableCommentWhitespaceWinTest\.php + tests/Core/Tokenizer/PHP/StableCommentWhitespaceWinTest\.php diff --git a/tests/Core/Tokenizer/AnonClassParenthesisOwnerTest.inc b/tests/Core/Tokenizer/PHP/AnonClassParenthesisOwnerTest.inc similarity index 100% rename from tests/Core/Tokenizer/AnonClassParenthesisOwnerTest.inc rename to tests/Core/Tokenizer/PHP/AnonClassParenthesisOwnerTest.inc diff --git a/tests/Core/Tokenizer/AnonClassParenthesisOwnerTest.php b/tests/Core/Tokenizer/PHP/AnonClassParenthesisOwnerTest.php similarity index 98% rename from tests/Core/Tokenizer/AnonClassParenthesisOwnerTest.php rename to tests/Core/Tokenizer/PHP/AnonClassParenthesisOwnerTest.php index 79eb742e19..5277dade14 100644 --- a/tests/Core/Tokenizer/AnonClassParenthesisOwnerTest.php +++ b/tests/Core/Tokenizer/PHP/AnonClassParenthesisOwnerTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class AnonClassParenthesisOwnerTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/ArrayKeywordTest.inc b/tests/Core/Tokenizer/PHP/ArrayKeywordTest.inc similarity index 100% rename from tests/Core/Tokenizer/ArrayKeywordTest.inc rename to tests/Core/Tokenizer/PHP/ArrayKeywordTest.inc diff --git a/tests/Core/Tokenizer/ArrayKeywordTest.php b/tests/Core/Tokenizer/PHP/ArrayKeywordTest.php similarity index 85% rename from tests/Core/Tokenizer/ArrayKeywordTest.php rename to tests/Core/Tokenizer/PHP/ArrayKeywordTest.php index c6dac85978..37528d6d70 100644 --- a/tests/Core/Tokenizer/ArrayKeywordTest.php +++ b/tests/Core/Tokenizer/PHP/ArrayKeywordTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class ArrayKeywordTest extends AbstractTokenizerTestCase { @@ -21,7 +23,6 @@ final class ArrayKeywordTest extends AbstractTokenizerTestCase * * @dataProvider dataArrayKeyword * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize - * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap * * @return void */ @@ -35,10 +36,6 @@ public function testArrayKeyword($testMarker, $testContent='array') $this->assertSame(T_ARRAY, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_ARRAY (code)'); $this->assertSame('T_ARRAY', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_ARRAY (type)'); - $this->assertArrayHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is not set'); - $this->assertArrayHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is not set'); - $this->assertArrayHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is not set'); - }//end testArrayKeyword() @@ -84,7 +81,6 @@ public static function dataArrayKeyword() * * @dataProvider dataArrayType * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize - * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap * * @return void */ @@ -98,10 +94,6 @@ public function testArrayType($testMarker, $testContent='array') $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); - $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); - $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); - $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); - }//end testArrayType() @@ -163,7 +155,6 @@ public static function dataArrayType() * * @dataProvider dataNotArrayKeyword * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize - * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap * * @return void */ @@ -177,10 +168,6 @@ public function testNotArrayKeyword($testMarker, $testContent='array') $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); - $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); - $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); - $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); - }//end testNotArrayKeyword() diff --git a/tests/Core/Tokenizer/AttributesTest.inc b/tests/Core/Tokenizer/PHP/AttributesTest.inc similarity index 100% rename from tests/Core/Tokenizer/AttributesTest.inc rename to tests/Core/Tokenizer/PHP/AttributesTest.inc diff --git a/tests/Core/Tokenizer/AttributesTest.php b/tests/Core/Tokenizer/PHP/AttributesTest.php similarity index 99% rename from tests/Core/Tokenizer/AttributesTest.php rename to tests/Core/Tokenizer/PHP/AttributesTest.php index 764a9bef42..24b7f07953 100644 --- a/tests/Core/Tokenizer/AttributesTest.php +++ b/tests/Core/Tokenizer/PHP/AttributesTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class AttributesTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/BackfillEnumTest.inc b/tests/Core/Tokenizer/PHP/BackfillEnumTest.inc similarity index 100% rename from tests/Core/Tokenizer/BackfillEnumTest.inc rename to tests/Core/Tokenizer/PHP/BackfillEnumTest.inc diff --git a/tests/Core/Tokenizer/BackfillEnumTest.php b/tests/Core/Tokenizer/PHP/BackfillEnumTest.php similarity index 98% rename from tests/Core/Tokenizer/BackfillEnumTest.php rename to tests/Core/Tokenizer/PHP/BackfillEnumTest.php index 3ce48f6553..d97a90b807 100644 --- a/tests/Core/Tokenizer/BackfillEnumTest.php +++ b/tests/Core/Tokenizer/PHP/BackfillEnumTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class BackfillEnumTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.inc b/tests/Core/Tokenizer/PHP/BackfillExplicitOctalNotationTest.inc similarity index 100% rename from tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.inc rename to tests/Core/Tokenizer/PHP/BackfillExplicitOctalNotationTest.inc diff --git a/tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.php b/tests/Core/Tokenizer/PHP/BackfillExplicitOctalNotationTest.php similarity index 97% rename from tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.php rename to tests/Core/Tokenizer/PHP/BackfillExplicitOctalNotationTest.php index ffa03cc884..64c82be3e4 100644 --- a/tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.php +++ b/tests/Core/Tokenizer/PHP/BackfillExplicitOctalNotationTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class BackfillExplicitOctalNotationTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/BackfillFnTokenTest.inc b/tests/Core/Tokenizer/PHP/BackfillFnTokenTest.inc similarity index 100% rename from tests/Core/Tokenizer/BackfillFnTokenTest.inc rename to tests/Core/Tokenizer/PHP/BackfillFnTokenTest.inc diff --git a/tests/Core/Tokenizer/BackfillFnTokenTest.php b/tests/Core/Tokenizer/PHP/BackfillFnTokenTest.php similarity index 99% rename from tests/Core/Tokenizer/BackfillFnTokenTest.php rename to tests/Core/Tokenizer/PHP/BackfillFnTokenTest.php index 194a85102d..2632337a5c 100644 --- a/tests/Core/Tokenizer/BackfillFnTokenTest.php +++ b/tests/Core/Tokenizer/PHP/BackfillFnTokenTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class BackfillFnTokenTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/BackfillMatchTokenTest.inc b/tests/Core/Tokenizer/PHP/BackfillMatchTokenTest.inc similarity index 100% rename from tests/Core/Tokenizer/BackfillMatchTokenTest.inc rename to tests/Core/Tokenizer/PHP/BackfillMatchTokenTest.inc diff --git a/tests/Core/Tokenizer/BackfillMatchTokenTest.php b/tests/Core/Tokenizer/PHP/BackfillMatchTokenTest.php similarity index 99% rename from tests/Core/Tokenizer/BackfillMatchTokenTest.php rename to tests/Core/Tokenizer/PHP/BackfillMatchTokenTest.php index 9f7df35402..42076c0422 100644 --- a/tests/Core/Tokenizer/BackfillMatchTokenTest.php +++ b/tests/Core/Tokenizer/PHP/BackfillMatchTokenTest.php @@ -8,8 +8,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; use PHP_CodeSniffer\Util\Tokens; final class BackfillMatchTokenTest extends AbstractTokenizerTestCase diff --git a/tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc b/tests/Core/Tokenizer/PHP/BackfillNumericSeparatorTest.inc similarity index 100% rename from tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc rename to tests/Core/Tokenizer/PHP/BackfillNumericSeparatorTest.inc diff --git a/tests/Core/Tokenizer/BackfillNumericSeparatorTest.php b/tests/Core/Tokenizer/PHP/BackfillNumericSeparatorTest.php similarity index 99% rename from tests/Core/Tokenizer/BackfillNumericSeparatorTest.php rename to tests/Core/Tokenizer/PHP/BackfillNumericSeparatorTest.php index b27dd8a059..53146730c7 100644 --- a/tests/Core/Tokenizer/BackfillNumericSeparatorTest.php +++ b/tests/Core/Tokenizer/PHP/BackfillNumericSeparatorTest.php @@ -7,8 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; use PHP_CodeSniffer\Util\Tokens; final class BackfillNumericSeparatorTest extends AbstractTokenizerTestCase diff --git a/tests/Core/Tokenizer/BackfillReadonlyTest.inc b/tests/Core/Tokenizer/PHP/BackfillReadonlyTest.inc similarity index 100% rename from tests/Core/Tokenizer/BackfillReadonlyTest.inc rename to tests/Core/Tokenizer/PHP/BackfillReadonlyTest.inc diff --git a/tests/Core/Tokenizer/BackfillReadonlyTest.php b/tests/Core/Tokenizer/PHP/BackfillReadonlyTest.php similarity index 99% rename from tests/Core/Tokenizer/BackfillReadonlyTest.php rename to tests/Core/Tokenizer/PHP/BackfillReadonlyTest.php index 0befb47b75..7756afaf08 100644 --- a/tests/Core/Tokenizer/BackfillReadonlyTest.php +++ b/tests/Core/Tokenizer/PHP/BackfillReadonlyTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class BackfillReadonlyTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/BitwiseOrTest.inc b/tests/Core/Tokenizer/PHP/BitwiseOrTest.inc similarity index 100% rename from tests/Core/Tokenizer/BitwiseOrTest.inc rename to tests/Core/Tokenizer/PHP/BitwiseOrTest.inc diff --git a/tests/Core/Tokenizer/BitwiseOrTest.php b/tests/Core/Tokenizer/PHP/BitwiseOrTest.php similarity index 98% rename from tests/Core/Tokenizer/BitwiseOrTest.php rename to tests/Core/Tokenizer/PHP/BitwiseOrTest.php index ade73e1af4..0648d61323 100644 --- a/tests/Core/Tokenizer/BitwiseOrTest.php +++ b/tests/Core/Tokenizer/PHP/BitwiseOrTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class BitwiseOrTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.inc b/tests/Core/Tokenizer/PHP/ContextSensitiveKeywordsTest.inc similarity index 100% rename from tests/Core/Tokenizer/ContextSensitiveKeywordsTest.inc rename to tests/Core/Tokenizer/PHP/ContextSensitiveKeywordsTest.inc diff --git a/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.php b/tests/Core/Tokenizer/PHP/ContextSensitiveKeywordsTest.php similarity index 99% rename from tests/Core/Tokenizer/ContextSensitiveKeywordsTest.php rename to tests/Core/Tokenizer/PHP/ContextSensitiveKeywordsTest.php index f70b9caa89..57eb349546 100644 --- a/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.php +++ b/tests/Core/Tokenizer/PHP/ContextSensitiveKeywordsTest.php @@ -7,8 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; use PHP_CodeSniffer\Util\Tokens; final class ContextSensitiveKeywordsTest extends AbstractTokenizerTestCase diff --git a/tests/Core/Tokenizer/DNFTypesTest.inc b/tests/Core/Tokenizer/PHP/DNFTypesTest.inc similarity index 100% rename from tests/Core/Tokenizer/DNFTypesTest.inc rename to tests/Core/Tokenizer/PHP/DNFTypesTest.inc diff --git a/tests/Core/Tokenizer/DNFTypesTest.php b/tests/Core/Tokenizer/PHP/DNFTypesTest.php similarity index 83% rename from tests/Core/Tokenizer/DNFTypesTest.php rename to tests/Core/Tokenizer/PHP/DNFTypesTest.php index a0474e2fd0..cdbe1314a1 100644 --- a/tests/Core/Tokenizer/DNFTypesTest.php +++ b/tests/Core/Tokenizer/PHP/DNFTypesTest.php @@ -7,8 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; use PHP_CodeSniffer\Util\Tokens; final class DNFTypesTest extends AbstractTokenizerTestCase @@ -18,17 +19,16 @@ final class DNFTypesTest extends AbstractTokenizerTestCase /** * Test that parentheses when **not** used in a type declaration are correctly tokenized. * - * @param string $testMarker The comment prefacing the target token. - * @param int|false $owner Optional. The parentheses owner or false when no parentheses owner is expected. - * @param bool $skipCheckInside Optional. Skip checking correct token type inside the parentheses. - * Use judiciously for combined normal + DNF tests only. + * @param string $testMarker The comment prefacing the target token. + * @param bool $skipCheckInside Optional. Skip checking correct token type inside the parentheses. + * Use judiciously for combined normal + DNF tests only. * * @dataProvider dataNormalParentheses - * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createParenthesisNestingMap + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional * * @return void */ - public function testNormalParentheses($testMarker, $owner=false, $skipCheckInside=false) + public function testNormalParentheses($testMarker, $skipCheckInside=false) { $tokens = $this->phpcsFile->getTokens(); @@ -39,17 +39,6 @@ public function testNormalParentheses($testMarker, $owner=false, $skipCheckInsid $this->assertSame(T_OPEN_PARENTHESIS, $opener['code'], 'Token tokenized as '.$opener['type'].', not T_OPEN_PARENTHESIS (code)'); $this->assertSame('T_OPEN_PARENTHESIS', $opener['type'], 'Token tokenized as '.$opener['type'].', not T_OPEN_PARENTHESIS (type)'); - if ($owner !== false) { - $this->assertArrayHasKey('parenthesis_owner', $opener, 'Parenthesis owner is not set'); - $this->assertSame(($openPtr + $owner), $opener['parenthesis_owner'], 'Opener parenthesis owner is not the expected token'); - } else { - $this->assertArrayNotHasKey('parenthesis_owner', $opener, 'Parenthesis owner is set'); - } - - $this->assertArrayHasKey('parenthesis_opener', $opener, 'Parenthesis opener is not set'); - $this->assertArrayHasKey('parenthesis_closer', $opener, 'Parenthesis closer is not set'); - $this->assertSame($openPtr, $opener['parenthesis_opener'], 'Parenthesis opener is not the expected token'); - $closePtr = $opener['parenthesis_closer']; $closer = $tokens[$closePtr]; @@ -57,22 +46,7 @@ public function testNormalParentheses($testMarker, $owner=false, $skipCheckInsid $this->assertSame(T_CLOSE_PARENTHESIS, $closer['code'], 'Token tokenized as '.$closer['type'].', not T_CLOSE_PARENTHESIS (code)'); $this->assertSame('T_CLOSE_PARENTHESIS', $closer['type'], 'Token tokenized as '.$closer['type'].', not T_CLOSE_PARENTHESIS (type)'); - if ($owner !== false) { - $this->assertArrayHasKey('parenthesis_owner', $closer, 'Parenthesis owner is not set'); - $this->assertSame(($openPtr + $owner), $closer['parenthesis_owner'], 'Closer parenthesis owner is not the expected token'); - } else { - $this->assertArrayNotHasKey('parenthesis_owner', $closer, 'Parenthesis owner is set'); - } - - $this->assertArrayHasKey('parenthesis_opener', $closer, 'Parenthesis opener is not set'); - $this->assertArrayHasKey('parenthesis_closer', $closer, 'Parenthesis closer is not set'); - $this->assertSame($closePtr, $closer['parenthesis_closer'], 'Parenthesis closer is not the expected token'); - for ($i = ($openPtr + 1); $i < $closePtr; $i++) { - $this->assertArrayHasKey('nested_parenthesis', $tokens[$i], "Nested parenthesis key not set on token $i ({$tokens[$i]['type']})"); - $this->assertArrayHasKey($openPtr, $tokens[$i]['nested_parenthesis'], 'Nested parenthesis is missing target parentheses set'); - $this->assertSame($closePtr, $tokens[$i]['nested_parenthesis'][$openPtr], 'Nested parenthesis closer not set correctly'); - // If there are ampersands, make sure these are tokenized as bitwise and. if ($skipCheckInside === false && $tokens[$i]['content'] === '&') { $this->assertSame(T_BITWISE_AND, $tokens[$i]['code'], 'Token tokenized as '.$tokens[$i]['type'].', not T_BITWISE_AND (code)'); @@ -133,44 +107,36 @@ public static function dataNormalParentheses() ], 'parens with owner: function; & in default value' => [ 'testMarker' => '/* testParensOwnerFunctionAmpersandInDefaultValue */', - 'owner' => -3, ], 'parens with owner: closure; param declared by & ref' => [ 'testMarker' => '/* testParensOwnerClosureAmpersandParamRef */', - 'owner' => -1, ], 'parens with owner: if' => [ 'testMarker' => '/* testParensOwnerIf */', - 'owner' => -2, ], 'parens without owner in if condition' => [ 'testMarker' => '/* testParensNoOwnerInIfCondition */', ], 'parens with owner: for' => [ 'testMarker' => '/* testParensOwnerFor */', - 'owner' => -2, ], 'parens without owner in for condition' => [ 'testMarker' => '/* testParensNoOwnerInForCondition */', ], 'parens with owner: match' => [ 'testMarker' => '/* testParensOwnerMatch */', - 'owner' => -1, ], 'parens with owner: array' => [ 'testMarker' => '/* testParensOwnerArray */', - 'owner' => -2, ], 'parens without owner in array; function call with & in callable' => [ 'testMarker' => '/* testParensNoOwnerFunctionCallWithAmpersandInCallable */', ], 'parens with owner: fn; & in return value' => [ 'testMarker' => '/* testParensOwnerArrowFn */', - 'owner' => -1, ], 'parens with owner: list with reference vars' => [ 'testMarker' => '/* testParensOwnerListWithRefVars */', - 'owner' => -1, ], 'parens without owner, function call with DNF look-a-like param' => [ 'testMarker' => '/* testParensNoOwnerFunctionCallwithDNFLookALikeParam */', @@ -199,11 +165,9 @@ public static function dataNormalParentheses() ], 'parens with owner: closure; & in default value' => [ 'testMarker' => '/* testParensOwnerClosureAmpersandInDefaultValue */', - 'owner' => -2, ], 'parens with owner: fn; dnf used within' => [ 'testMarker' => '/* testParensOwnerArrowDNFUsedWithin */', - 'owner' => -2, 'skipCheckInside' => true, ], 'parens without owner: default value for param in arrow function' => [ @@ -228,7 +192,6 @@ public static function dataNormalParentheses() * * @dataProvider dataDNFTypeParentheses * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional - * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createParenthesisNestingMap * * @return void */ @@ -243,11 +206,6 @@ public function testDNFTypeParentheses($testMarker) $this->assertSame(T_TYPE_OPEN_PARENTHESIS, $opener['code'], 'Token tokenized as '.$opener['type'].', not T_TYPE_OPEN_PARENTHESIS (code)'); $this->assertSame('T_TYPE_OPEN_PARENTHESIS', $opener['type'], 'Token tokenized as '.$opener['type'].', not T_TYPE_OPEN_PARENTHESIS (type)'); - $this->assertArrayNotHasKey('parenthesis_owner', $opener, 'Parenthesis owner is set'); - $this->assertArrayHasKey('parenthesis_opener', $opener, 'Parenthesis opener is not set'); - $this->assertArrayHasKey('parenthesis_closer', $opener, 'Parenthesis closer is not set'); - $this->assertSame($openPtr, $opener['parenthesis_opener'], 'Parenthesis opener is not the expected token'); - $closePtr = $opener['parenthesis_closer']; $closer = $tokens[$closePtr]; @@ -255,17 +213,8 @@ public function testDNFTypeParentheses($testMarker) $this->assertSame(T_TYPE_CLOSE_PARENTHESIS, $closer['code'], 'Token tokenized as '.$closer['type'].', not T_TYPE_CLOSE_PARENTHESIS (code)'); $this->assertSame('T_TYPE_CLOSE_PARENTHESIS', $closer['type'], 'Token tokenized as '.$closer['type'].', not T_TYPE_CLOSE_PARENTHESIS (type)'); - $this->assertArrayNotHasKey('parenthesis_owner', $closer, 'Parenthesis owner is set'); - $this->assertArrayHasKey('parenthesis_opener', $closer, 'Parenthesis opener is not set'); - $this->assertArrayHasKey('parenthesis_closer', $closer, 'Parenthesis closer is not set'); - $this->assertSame($closePtr, $closer['parenthesis_closer'], 'Parenthesis closer is not the expected token'); - $intersectionCount = 0; for ($i = ($openPtr + 1); $i < $closePtr; $i++) { - $this->assertArrayHasKey('nested_parenthesis', $tokens[$i], "Nested parenthesis key not set on token $i ({$tokens[$i]['type']})"); - $this->assertArrayHasKey($openPtr, $tokens[$i]['nested_parenthesis'], 'Nested parenthesis is missing target parentheses set'); - $this->assertSame($closePtr, $tokens[$i]['nested_parenthesis'][$openPtr], 'Nested parenthesis closer not set correctly'); - if ($tokens[$i]['content'] === '&') { $this->assertSame( T_TYPE_INTERSECTION, diff --git a/tests/Core/Tokenizer/DefaultKeywordTest.inc b/tests/Core/Tokenizer/PHP/DefaultKeywordTest.inc similarity index 100% rename from tests/Core/Tokenizer/DefaultKeywordTest.inc rename to tests/Core/Tokenizer/PHP/DefaultKeywordTest.inc diff --git a/tests/Core/Tokenizer/PHP/DefaultKeywordTest.php b/tests/Core/Tokenizer/PHP/DefaultKeywordTest.php new file mode 100644 index 0000000000..c32d337547 --- /dev/null +++ b/tests/Core/Tokenizer/PHP/DefaultKeywordTest.php @@ -0,0 +1,255 @@ + + * @copyright 2020-2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @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 DefaultKeywordTest extends AbstractTokenizerTestCase +{ + + + /** + * Test the retokenization of the `default` keyword for match structure to `T_MATCH_DEFAULT`. + * + * Note: Cases and default structures within a match structure do *NOT* get case/default scope + * conditions, in contrast to case and default structures in switch control structures. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataMatchDefault + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testMatchDefault($testMarker, $testContent='default') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_MATCH_DEFAULT, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_DEFAULT (code)'); + $this->assertSame('T_MATCH_DEFAULT', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_DEFAULT (type)'); + + }//end testMatchDefault() + + + /** + * Data provider. + * + * @see testMatchDefault() + * + * @return array> + */ + public static function dataMatchDefault() + { + return [ + 'simple_match_default' => [ + 'testMarker' => '/* testSimpleMatchDefault */', + ], + 'match_default_in_switch_case_1' => [ + 'testMarker' => '/* testMatchDefaultNestedInSwitchCase1 */', + ], + 'match_default_in_switch_case_2' => [ + 'testMarker' => '/* testMatchDefaultNestedInSwitchCase2 */', + ], + 'match_default_in_switch_default' => [ + 'testMarker' => '/* testMatchDefaultNestedInSwitchDefault */', + ], + 'match_default_containing_switch' => [ + 'testMarker' => '/* testMatchDefault */', + ], + + 'match_default_with_nested_long_array_and_default_key' => [ + 'testMarker' => '/* testMatchDefaultWithNestedLongArrayWithClassConstantKey */', + 'testContent' => 'DEFAULT', + ], + 'match_default_with_nested_long_array_and_default_key_2' => [ + 'testMarker' => '/* testMatchDefaultWithNestedLongArrayWithClassConstantKeyLevelDown */', + 'testContent' => 'DEFAULT', + ], + 'match_default_with_nested_short_array_and_default_key' => [ + 'testMarker' => '/* testMatchDefaultWithNestedShortArrayWithClassConstantKey */', + 'testContent' => 'DEFAULT', + ], + 'match_default_with_nested_short_array_and_default_key_2' => [ + 'testMarker' => '/* testMatchDefaultWithNestedShortArrayWithClassConstantKeyLevelDown */', + 'testContent' => 'DEFAULT', + ], + 'match_default_in_long_array' => [ + 'testMarker' => '/* testMatchDefaultNestedInLongArray */', + 'testContent' => 'DEFAULT', + ], + 'match_default_in_short_array' => [ + 'testMarker' => '/* testMatchDefaultNestedInShortArray */', + 'testContent' => 'DEFAULT', + ], + ]; + + }//end dataMatchDefault() + + + /** + * Verify that the retokenization of `T_DEFAULT` tokens in match constructs, doesn't negatively + * impact the tokenization of `T_DEFAULT` tokens in switch control structures. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataSwitchDefault + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testSwitchDefault($testMarker, $testContent='default') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_DEFAULT, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_DEFAULT (code)'); + $this->assertSame('T_DEFAULT', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_DEFAULT (type)'); + + }//end testSwitchDefault() + + + /** + * Data provider. + * + * @see testSwitchDefault() + * + * @return array> + */ + public static function dataSwitchDefault() + { + return [ + 'simple_switch_default' => [ + 'testMarker' => '/* testSimpleSwitchDefault */', + ], + 'simple_switch_default_with_curlies' => [ + 'testMarker' => '/* testSimpleSwitchDefaultWithCurlies */', + ], + 'switch_default_toplevel' => [ + 'testMarker' => '/* testSwitchDefault */', + ], + 'switch_default_nested_in_match_case' => [ + 'testMarker' => '/* testSwitchDefaultNestedInMatchCase */', + ], + 'switch_default_nested_in_match_default' => [ + 'testMarker' => '/* testSwitchDefaultNestedInMatchDefault */', + ], + ]; + + }//end dataSwitchDefault() + + + /** + * Verify that the retokenization of `T_DEFAULT` tokens in match constructs, doesn't negatively + * impact the tokenization of `T_STRING` tokens with the contents 'default' which aren't in + * actual fact the default keyword. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotDefaultKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNotDefaultKeyword($testMarker, $testContent='DEFAULT') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + }//end testNotDefaultKeyword() + + + /** + * Data provider. + * + * @see testNotDefaultKeyword() + * + * @return array> + */ + public static function dataNotDefaultKeyword() + { + return [ + 'class-constant-as-short-array-key' => [ + 'testMarker' => '/* testClassConstantAsShortArrayKey */', + ], + 'class-property-as-short-array-key' => [ + 'testMarker' => '/* testClassPropertyAsShortArrayKey */', + ], + 'namespaced-constant-as-short-array-key' => [ + 'testMarker' => '/* testNamespacedConstantAsShortArrayKey */', + ], + 'fqn-global-constant-as-short-array-key' => [ + 'testMarker' => '/* testFQNGlobalConstantAsShortArrayKey */', + ], + 'class-constant-as-long-array-key' => [ + 'testMarker' => '/* testClassConstantAsLongArrayKey */', + ], + 'class-constant-as-yield-key' => [ + 'testMarker' => '/* testClassConstantAsYieldKey */', + ], + + 'class-constant-as-long-array-key-nested-in-match' => [ + 'testMarker' => '/* testClassConstantAsLongArrayKeyNestedInMatch */', + ], + 'class-constant-as-long-array-key-nested-in-match-2' => [ + 'testMarker' => '/* testClassConstantAsLongArrayKeyNestedInMatchLevelDown */', + ], + 'class-constant-as-short-array-key-nested-in-match' => [ + 'testMarker' => '/* testClassConstantAsShortArrayKeyNestedInMatch */', + ], + 'class-constant-as-short-array-key-nested-in-match-2' => [ + 'testMarker' => '/* testClassConstantAsShortArrayKeyNestedInMatchLevelDown */', + ], + 'class-constant-as-long-array-key-with-nested-match' => [ + 'testMarker' => '/* testClassConstantAsLongArrayKeyWithNestedMatch */', + ], + 'class-constant-as-short-array-key-with-nested-match' => [ + 'testMarker' => '/* testClassConstantAsShortArrayKeyWithNestedMatch */', + ], + + 'class-constant-in-switch-case' => [ + 'testMarker' => '/* testClassConstantInSwitchCase */', + ], + 'class-property-in-switch-case' => [ + 'testMarker' => '/* testClassPropertyInSwitchCase */', + ], + 'namespaced-constant-in-switch-case' => [ + 'testMarker' => '/* testNamespacedConstantInSwitchCase */', + ], + 'namespace-relative-constant-in-switch-case' => [ + 'testMarker' => '/* testNamespaceRelativeConstantInSwitchCase */', + ], + + 'class-constant-declaration' => [ + 'testMarker' => '/* testClassConstant */', + ], + 'class-method-declaration' => [ + 'testMarker' => '/* testMethodDeclaration */', + 'testContent' => 'default', + ], + ]; + + }//end dataNotDefaultKeyword() + + +}//end class diff --git a/tests/Core/Tokenizer/DoubleArrowTest.inc b/tests/Core/Tokenizer/PHP/DoubleArrowTest.inc similarity index 100% rename from tests/Core/Tokenizer/DoubleArrowTest.inc rename to tests/Core/Tokenizer/PHP/DoubleArrowTest.inc diff --git a/tests/Core/Tokenizer/DoubleArrowTest.php b/tests/Core/Tokenizer/PHP/DoubleArrowTest.php similarity index 99% rename from tests/Core/Tokenizer/DoubleArrowTest.php rename to tests/Core/Tokenizer/PHP/DoubleArrowTest.php index 768ff65d74..2d050d2518 100644 --- a/tests/Core/Tokenizer/DoubleArrowTest.php +++ b/tests/Core/Tokenizer/PHP/DoubleArrowTest.php @@ -9,7 +9,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class DoubleArrowTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/DoubleQuotedStringTest.inc b/tests/Core/Tokenizer/PHP/DoubleQuotedStringTest.inc similarity index 100% rename from tests/Core/Tokenizer/DoubleQuotedStringTest.inc rename to tests/Core/Tokenizer/PHP/DoubleQuotedStringTest.inc diff --git a/tests/Core/Tokenizer/DoubleQuotedStringTest.php b/tests/Core/Tokenizer/PHP/DoubleQuotedStringTest.php similarity index 98% rename from tests/Core/Tokenizer/DoubleQuotedStringTest.php rename to tests/Core/Tokenizer/PHP/DoubleQuotedStringTest.php index 83ba0aab7a..6fb3643f95 100644 --- a/tests/Core/Tokenizer/DoubleQuotedStringTest.php +++ b/tests/Core/Tokenizer/PHP/DoubleQuotedStringTest.php @@ -8,7 +8,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class DoubleQuotedStringTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/EnumCaseTest.inc b/tests/Core/Tokenizer/PHP/EnumCaseTest.inc similarity index 100% rename from tests/Core/Tokenizer/EnumCaseTest.inc rename to tests/Core/Tokenizer/PHP/EnumCaseTest.inc diff --git a/tests/Core/Tokenizer/EnumCaseTest.php b/tests/Core/Tokenizer/PHP/EnumCaseTest.php similarity index 89% rename from tests/Core/Tokenizer/EnumCaseTest.php rename to tests/Core/Tokenizer/PHP/EnumCaseTest.php index f5b68507d6..f80e19dc32 100644 --- a/tests/Core/Tokenizer/EnumCaseTest.php +++ b/tests/Core/Tokenizer/PHP/EnumCaseTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class EnumCaseTest extends AbstractTokenizerTestCase { @@ -20,7 +22,6 @@ final class EnumCaseTest extends AbstractTokenizerTestCase * * @dataProvider dataEnumCases * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize - * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap * * @return void */ @@ -33,10 +34,6 @@ public function testEnumCases($testMarker) $this->assertSame(T_ENUM_CASE, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_ENUM_CASE (code)'); $this->assertSame('T_ENUM_CASE', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_ENUM_CASE (type)'); - $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); - $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); - $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); - }//end testEnumCases() @@ -69,7 +66,6 @@ public static function dataEnumCases() * * @dataProvider dataNotEnumCases * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize - * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap * * @return void */ @@ -82,10 +78,6 @@ public function testNotEnumCases($testMarker) $this->assertSame(T_CASE, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_CASE (code)'); $this->assertSame('T_CASE', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_CASE (type)'); - $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition is not set'); - $this->assertArrayHasKey('scope_opener', $tokenArray, 'Scope opener is not set'); - $this->assertArrayHasKey('scope_closer', $tokenArray, 'Scope closer is not set'); - }//end testNotEnumCases() diff --git a/tests/Core/Tokenizer/FinallyTest.inc b/tests/Core/Tokenizer/PHP/FinallyTest.inc similarity index 100% rename from tests/Core/Tokenizer/FinallyTest.inc rename to tests/Core/Tokenizer/PHP/FinallyTest.inc diff --git a/tests/Core/Tokenizer/FinallyTest.php b/tests/Core/Tokenizer/PHP/FinallyTest.php similarity index 96% rename from tests/Core/Tokenizer/FinallyTest.php rename to tests/Core/Tokenizer/PHP/FinallyTest.php index a73ac57e50..d74c781ae3 100644 --- a/tests/Core/Tokenizer/FinallyTest.php +++ b/tests/Core/Tokenizer/PHP/FinallyTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class FinallyTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/GotoLabelTest.inc b/tests/Core/Tokenizer/PHP/GotoLabelTest.inc similarity index 100% rename from tests/Core/Tokenizer/GotoLabelTest.inc rename to tests/Core/Tokenizer/PHP/GotoLabelTest.inc diff --git a/tests/Core/Tokenizer/GotoLabelTest.php b/tests/Core/Tokenizer/PHP/GotoLabelTest.php similarity index 97% rename from tests/Core/Tokenizer/GotoLabelTest.php rename to tests/Core/Tokenizer/PHP/GotoLabelTest.php index 6917e939ea..8e6a5f5ceb 100644 --- a/tests/Core/Tokenizer/GotoLabelTest.php +++ b/tests/Core/Tokenizer/PHP/GotoLabelTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class GotoLabelTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/HeredocStringTest.inc b/tests/Core/Tokenizer/PHP/HeredocStringTest.inc similarity index 100% rename from tests/Core/Tokenizer/HeredocStringTest.inc rename to tests/Core/Tokenizer/PHP/HeredocStringTest.inc diff --git a/tests/Core/Tokenizer/HeredocStringTest.php b/tests/Core/Tokenizer/PHP/HeredocStringTest.php similarity index 98% rename from tests/Core/Tokenizer/HeredocStringTest.php rename to tests/Core/Tokenizer/PHP/HeredocStringTest.php index da3f361b2d..75f64d4799 100644 --- a/tests/Core/Tokenizer/HeredocStringTest.php +++ b/tests/Core/Tokenizer/PHP/HeredocStringTest.php @@ -8,7 +8,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class HeredocStringTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.inc b/tests/Core/Tokenizer/PHP/NamedFunctionCallArgumentsTest.inc similarity index 100% rename from tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.inc rename to tests/Core/Tokenizer/PHP/NamedFunctionCallArgumentsTest.inc diff --git a/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.php b/tests/Core/Tokenizer/PHP/NamedFunctionCallArgumentsTest.php similarity index 99% rename from tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.php rename to tests/Core/Tokenizer/PHP/NamedFunctionCallArgumentsTest.php index 058129f560..14d0c6da51 100644 --- a/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.php +++ b/tests/Core/Tokenizer/PHP/NamedFunctionCallArgumentsTest.php @@ -7,8 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; use PHP_CodeSniffer\Util\Tokens; final class NamedFunctionCallArgumentsTest extends AbstractTokenizerTestCase diff --git a/tests/Core/Tokenizer/NullsafeObjectOperatorTest.inc b/tests/Core/Tokenizer/PHP/NullsafeObjectOperatorTest.inc similarity index 100% rename from tests/Core/Tokenizer/NullsafeObjectOperatorTest.inc rename to tests/Core/Tokenizer/PHP/NullsafeObjectOperatorTest.inc diff --git a/tests/Core/Tokenizer/NullsafeObjectOperatorTest.php b/tests/Core/Tokenizer/PHP/NullsafeObjectOperatorTest.php similarity index 97% rename from tests/Core/Tokenizer/NullsafeObjectOperatorTest.php rename to tests/Core/Tokenizer/PHP/NullsafeObjectOperatorTest.php index f97ff69786..95bfc154ea 100644 --- a/tests/Core/Tokenizer/NullsafeObjectOperatorTest.php +++ b/tests/Core/Tokenizer/PHP/NullsafeObjectOperatorTest.php @@ -7,8 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; use PHP_CodeSniffer\Util\Tokens; final class NullsafeObjectOperatorTest extends AbstractTokenizerTestCase diff --git a/tests/Core/Tokenizer/OtherContextSensitiveKeywordsTest.inc b/tests/Core/Tokenizer/PHP/OtherContextSensitiveKeywordsTest.inc similarity index 100% rename from tests/Core/Tokenizer/OtherContextSensitiveKeywordsTest.inc rename to tests/Core/Tokenizer/PHP/OtherContextSensitiveKeywordsTest.inc diff --git a/tests/Core/Tokenizer/OtherContextSensitiveKeywordsTest.php b/tests/Core/Tokenizer/PHP/OtherContextSensitiveKeywordsTest.php similarity index 99% rename from tests/Core/Tokenizer/OtherContextSensitiveKeywordsTest.php rename to tests/Core/Tokenizer/PHP/OtherContextSensitiveKeywordsTest.php index 1b8d19881d..3eff0e96d6 100644 --- a/tests/Core/Tokenizer/OtherContextSensitiveKeywordsTest.php +++ b/tests/Core/Tokenizer/PHP/OtherContextSensitiveKeywordsTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; /** * Tests the conversion of PHPCS native context sensitive keyword tokens to T_STRING. diff --git a/tests/Core/Tokenizer/ResolveSimpleTokenTest.inc b/tests/Core/Tokenizer/PHP/ResolveSimpleTokenTest.inc similarity index 100% rename from tests/Core/Tokenizer/ResolveSimpleTokenTest.inc rename to tests/Core/Tokenizer/PHP/ResolveSimpleTokenTest.inc diff --git a/tests/Core/Tokenizer/ResolveSimpleTokenTest.php b/tests/Core/Tokenizer/PHP/ResolveSimpleTokenTest.php similarity index 98% rename from tests/Core/Tokenizer/ResolveSimpleTokenTest.php rename to tests/Core/Tokenizer/PHP/ResolveSimpleTokenTest.php index 706b1fe3c7..4045f775a4 100644 --- a/tests/Core/Tokenizer/ResolveSimpleTokenTest.php +++ b/tests/Core/Tokenizer/PHP/ResolveSimpleTokenTest.php @@ -7,8 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; use PHP_CodeSniffer\Util\Tokens; /** diff --git a/tests/Core/Tokenizer/ShortArrayTest.inc b/tests/Core/Tokenizer/PHP/ShortArrayTest.inc similarity index 100% rename from tests/Core/Tokenizer/ShortArrayTest.inc rename to tests/Core/Tokenizer/PHP/ShortArrayTest.inc diff --git a/tests/Core/Tokenizer/ShortArrayTest.php b/tests/Core/Tokenizer/PHP/ShortArrayTest.php similarity index 98% rename from tests/Core/Tokenizer/ShortArrayTest.php rename to tests/Core/Tokenizer/PHP/ShortArrayTest.php index 189523863e..06e76621ff 100644 --- a/tests/Core/Tokenizer/ShortArrayTest.php +++ b/tests/Core/Tokenizer/PHP/ShortArrayTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class ShortArrayTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/StableCommentWhitespaceTest.inc b/tests/Core/Tokenizer/PHP/StableCommentWhitespaceTest.inc similarity index 100% rename from tests/Core/Tokenizer/StableCommentWhitespaceTest.inc rename to tests/Core/Tokenizer/PHP/StableCommentWhitespaceTest.inc diff --git a/tests/Core/Tokenizer/StableCommentWhitespaceTest.php b/tests/Core/Tokenizer/PHP/StableCommentWhitespaceTest.php similarity index 99% rename from tests/Core/Tokenizer/StableCommentWhitespaceTest.php rename to tests/Core/Tokenizer/PHP/StableCommentWhitespaceTest.php index b3b19c6bae..6a58ccbbd7 100644 --- a/tests/Core/Tokenizer/StableCommentWhitespaceTest.php +++ b/tests/Core/Tokenizer/PHP/StableCommentWhitespaceTest.php @@ -13,8 +13,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; use PHP_CodeSniffer\Util\Tokens; final class StableCommentWhitespaceTest extends AbstractTokenizerTestCase diff --git a/tests/Core/Tokenizer/StableCommentWhitespaceWinTest.inc b/tests/Core/Tokenizer/PHP/StableCommentWhitespaceWinTest.inc similarity index 100% rename from tests/Core/Tokenizer/StableCommentWhitespaceWinTest.inc rename to tests/Core/Tokenizer/PHP/StableCommentWhitespaceWinTest.inc diff --git a/tests/Core/Tokenizer/StableCommentWhitespaceWinTest.php b/tests/Core/Tokenizer/PHP/StableCommentWhitespaceWinTest.php similarity index 99% rename from tests/Core/Tokenizer/StableCommentWhitespaceWinTest.php rename to tests/Core/Tokenizer/PHP/StableCommentWhitespaceWinTest.php index 2d0ce30d85..dbb103060a 100644 --- a/tests/Core/Tokenizer/StableCommentWhitespaceWinTest.php +++ b/tests/Core/Tokenizer/PHP/StableCommentWhitespaceWinTest.php @@ -10,8 +10,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; use PHP_CodeSniffer\Util\Tokens; final class StableCommentWhitespaceWinTest extends AbstractTokenizerTestCase diff --git a/tests/Core/Tokenizer/TypeIntersectionTest.inc b/tests/Core/Tokenizer/PHP/TypeIntersectionTest.inc similarity index 100% rename from tests/Core/Tokenizer/TypeIntersectionTest.inc rename to tests/Core/Tokenizer/PHP/TypeIntersectionTest.inc diff --git a/tests/Core/Tokenizer/TypeIntersectionTest.php b/tests/Core/Tokenizer/PHP/TypeIntersectionTest.php similarity index 98% rename from tests/Core/Tokenizer/TypeIntersectionTest.php rename to tests/Core/Tokenizer/PHP/TypeIntersectionTest.php index bcbc8918cb..99c96edce4 100644 --- a/tests/Core/Tokenizer/TypeIntersectionTest.php +++ b/tests/Core/Tokenizer/PHP/TypeIntersectionTest.php @@ -8,7 +8,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class TypeIntersectionTest extends AbstractTokenizerTestCase { diff --git a/tests/Core/Tokenizer/TypedConstantsTest.inc b/tests/Core/Tokenizer/PHP/TypedConstantsTest.inc similarity index 100% rename from tests/Core/Tokenizer/TypedConstantsTest.inc rename to tests/Core/Tokenizer/PHP/TypedConstantsTest.inc diff --git a/tests/Core/Tokenizer/TypedConstantsTest.php b/tests/Core/Tokenizer/PHP/TypedConstantsTest.php similarity index 99% rename from tests/Core/Tokenizer/TypedConstantsTest.php rename to tests/Core/Tokenizer/PHP/TypedConstantsTest.php index 8b66f926d3..60c21b9dc9 100644 --- a/tests/Core/Tokenizer/TypedConstantsTest.php +++ b/tests/Core/Tokenizer/PHP/TypedConstantsTest.php @@ -12,8 +12,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; use PHP_CodeSniffer\Util\Tokens; final class TypedConstantsTest extends AbstractTokenizerTestCase diff --git a/tests/Core/Tokenizer/UndoNamespacedNameSingleTokenTest.inc b/tests/Core/Tokenizer/PHP/UndoNamespacedNameSingleTokenTest.inc similarity index 100% rename from tests/Core/Tokenizer/UndoNamespacedNameSingleTokenTest.inc rename to tests/Core/Tokenizer/PHP/UndoNamespacedNameSingleTokenTest.inc diff --git a/tests/Core/Tokenizer/UndoNamespacedNameSingleTokenTest.php b/tests/Core/Tokenizer/PHP/UndoNamespacedNameSingleTokenTest.php similarity index 99% rename from tests/Core/Tokenizer/UndoNamespacedNameSingleTokenTest.php rename to tests/Core/Tokenizer/PHP/UndoNamespacedNameSingleTokenTest.php index 9e1038dcfb..18e2275768 100644 --- a/tests/Core/Tokenizer/UndoNamespacedNameSingleTokenTest.php +++ b/tests/Core/Tokenizer/PHP/UndoNamespacedNameSingleTokenTest.php @@ -17,8 +17,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP; +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; use PHP_CodeSniffer\Util\Tokens; final class UndoNamespacedNameSingleTokenTest extends AbstractTokenizerTestCase diff --git a/tests/Core/Tokenizer/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.inc b/tests/Core/Tokenizer/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.inc new file mode 100644 index 0000000000..6c671ebfdf --- /dev/null +++ b/tests/Core/Tokenizer/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.inc @@ -0,0 +1,185 @@ + 10 ) {} + +/* testParensOwnerFor */ +for ($i =0; $i < /* testParensNoOwnerInForCondition */ ( CONST_A & CONST_B ); $i++ ); + +/* testParensOwnerMatch */ +$match = match(CONST_A & CONST_B) { + default => $a, +}; + +/* testParensOwnerArray */ +$array = array ( + 'text', + \CONST_A & \Fully\Qualified\CONST_B, + /* testParensNoOwnerFunctionCallWithAmpersandInCallable */ + do_something($a, /* testParensOwnerArrowFn */ fn($b) => $a & $b, $c), +); + +/* testParensOwnerListWithRefVars */ +list(&$a, &$b) = $array; + +/* testParensNoOwnerFunctionCallwithDNFLookALikeParam */ +$obj->static((CONST_A&CONST_B)|CONST_C | $var); + + +/* + * DNF parentheses. + */ + +class DNFTypes { + /* testDNFTypeOOConstUnqualifiedClasses */ + public const (A&B)|D UNQUALIFIED = new Foo; + + /* testDNFTypeOOConstReverseModifierOrder */ + protected final const int|(Foo&Bar)|float MODIFIERS_REVERSED /* testParensNoOwnerOOConstDefaultValue */ = (E_WARNING & E_NOTICE) | E_DEPRECATED; + + const + /* testDNFTypeOOConstMulti1 */ + (A&B) | + /* testDNFTypeOOConstMulti2 */ + (C&D) | // phpcs:ignore Stnd.Cat.Sniff + /* testDNFTypeOOConstMulti3 */ + (Y&D) + | null MULTI_DNF = false; + + /* testDNFTypeOOConstNamespaceRelative */ + final protected const (namespace\Sub\NameA&namespace\Sub\NameB)|namespace\Sub\NameC NAMESPACE_RELATIVE = new namespace\Sub\NameB; + + /* testDNFTypeOOConstPartiallyQualified */ + const Partially\Qualified\NameC|(Partially\Qualified\NameA&Partially\Qualified\NameB) PARTIALLY_QUALIFIED = new Partially\Qualified\NameA; + + /* testDNFTypeOOConstFullyQualified */ + const (\Fully\Qualified\NameA&\Fully\Qualified\NameB)|\Fully\Qualified\NameC FULLY_QUALIFIED = new \Fully\Qualified\NameB(); + + /* testDNFTypePropertyUnqualifiedClasses */ + public static (Foo&Bar)|object $obj; + + /* testDNFTypePropertyReverseModifierOrder */ + static protected string|(A&B)|bool $dnf /* testParensNoOwnerPropertyDefaultValue1 */ = ( E_WARNING & E_NOTICE ) | /* testParensNoOwnerPropertyDefaultValue2 */ (E_ALL & E_DEPRECATED); + + private + /* testDNFTypePropertyMultiNamespaceRelative */ + (namespace\Sub\NameA&namespace\Sub\NameB) | + /* testDNFTypePropertyMultiPartiallyQualified */ + (Partially\Qualified\NameA&Partially\Qualified\NameB) | // phpcs:ignore Stnd.Cat.Sniff + false + /* testDNFTypePropertyMultiFullyQualified */ + | (\Fully\Qualified\NameA&\Fully\Qualified\NameB) $multiDnf; + + /* testDNFTypePropertyWithReadOnlyKeyword1 */ + protected readonly (A&B) | /* testDNFTypePropertyWithReadOnlyKeyword2 */ (C&D) $readonly; + + /* testDNFTypePropertyWithStaticAndReadOnlyKeywords */ + static readonly (A&B&C)|array $staticReadonly; + + /* testDNFTypePropertyWithOnlyStaticKeyword */ + static (A&B&C)|true $obj; + + public function paramTypes( + /* testDNFTypeParam1WithAttribute */ + #[MyAttribute] + (\Foo&Bar)|int|float $paramA /* testParensNoOwnerParamDefaultValue */ = SOMETHING | (CONSTANT_A & CONSTANT_B), + + /* testDNFTypeParam2 */ + (Foo&\Bar) /* testDNFTypeParam3 */ |(Baz&Fop) &...$paramB = null, + ) { + /* testParensNoOwnerInReturnValue1 */ + return ( + /* testParensNoOwnerInReturnValue2 */ + ($a1 & $b1) | + /* testParensNoOwnerInReturnValue3 */ + ($a2 & $b2) + ) + $c; + } + + public function identifierNames( + /* testDNFTypeParamNamespaceRelative */ + (namespace\Sub\NameA&namespace\Sub\NameB)|false $paramA, + /* testDNFTypeParamPartiallyQualified */ + Partially\Qualified\NameC|(Partially\Qualified\NameA&Partially\Qualified\NameB) $paramB, + /* testDNFTypeParamFullyQualified */ + name|(\Fully\Qualified\NameA&\Fully\Qualified\NameB) $paramC, + ) {} + + public function __construct( + /* testDNFTypeConstructorPropertyPromotion1 */ + public (A&B)| /* testDNFTypeConstructorPropertyPromotion2 */ (A&D) $property + ) {} + + public function returnType()/* testDNFTypeReturnType1 */ : A|(B&D)|/* testDNFTypeReturnType2 */(B&W)|null {} + + abstract public function abstractMethod(): /* testDNFTypeAbstractMethodReturnType1 */ (X&Y) /* testDNFTypeAbstractMethodReturnType2 */ |(W&Z); + + public function identifierNamesReturnRelative( + ) : /* testDNFTypeReturnTypeNamespaceRelative */ (namespace\Sub\NameA&namespace\Sub\NameB)|namespace\Sub\NameC {} + + public function identifierNamesReturnPQ( + ) : /* testDNFTypeReturnPartiallyQualified */Partially\Qualified\NameA|(Partially\Qualified\NameB&Partially\Qualified\NameC) {} + + // Illegal type: segments which are strict subsets of others are disallowed, but that's not the concern of the tokenizer. + public function identifierNamesReturnFQ( + ) /* testDNFTypeReturnFullyQualified */ : (\Fully\Qualified\NameA&\Fully\Qualified\NameB)|\Fully\Qualified\NameB {} +} + +function globalFunctionWithSpreadAndReference( + /* testDNFTypeWithReference */ + float|(B&A) &$paramA, + /* testDNFTypeWithSpreadOperator */ + string|(B|D) ...$paramB +) {} + + +$closureWithParamType = function ( /* testDNFTypeClosureParamIllegalNullable */ ?(A&B)|bool $string) {}; + +/* testParensOwnerClosureAmpersandInDefaultValue */ +$closureWithReturnType = function ($string = NONSENSE & FAKE) /* testDNFTypeClosureReturn */ : (\Package\MyA&PackageB)|null {}; + +/* testParensOwnerArrowDNFUsedWithin */ +$arrowWithParamType = fn ( + /* testDNFTypeArrowParam */ + object|(A&B&C)|array $param, + /* testParensNoOwnerAmpersandInDefaultValue */ ?int $int = (CONSTA & CONSTB )| CONST_C +) + /* testParensNoOwnerInArrowReturnExpression */ + => ($param & $foo ) | $int; + +$arrowWithReturnType = fn ($param) : /* testDNFTypeArrowReturnType */ int|(A&B) => $param * 10; + +$arrowWithParamReturnByRef = fn &( + /* testDNFTypeArrowParamWithReturnByRef */ + (A&B)|null $param +) => $param * 10; + +function InvalidSyntaxes( + /* testDNFTypeParamIllegalUnnecessaryParens */ + (A&B) $parensNotNeeded + + /* testDNFTypeParamIllegalIntersectUnionReversed */ + A&(B|D) $onlyIntersectAllowedWithinParensAndUnionOutside + + /* testDNFTypeParamIllegalNestedParens */ + A|(B&(D|W)|null) $nestedParensNotAllowed +) {} diff --git a/tests/Core/Tokenizer/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.php b/tests/Core/Tokenizer/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.php new file mode 100644 index 0000000000..7198690ddf --- /dev/null +++ b/tests/Core/Tokenizer/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.php @@ -0,0 +1,375 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; + +final class CreateParenthesisNestingMapDNFTypesTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that parentheses when **not** used in a type declaration are correctly tokenized. + * + * @param string $testMarker The comment prefacing the target token. + * @param int|false $owner Optional. The parentheses owner or false when no parentheses owner is expected. + * + * @dataProvider dataNormalParentheses + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createParenthesisNestingMap + * + * @return void + */ + public function testNormalParentheses($testMarker, $owner=false) + { + $tokens = $this->phpcsFile->getTokens(); + + $openPtr = $this->getTargetToken($testMarker, [T_OPEN_PARENTHESIS, T_TYPE_OPEN_PARENTHESIS]); + $opener = $tokens[$openPtr]; + + // Make sure we're looking at the right token. + $this->assertSame(T_OPEN_PARENTHESIS, $opener['code'], 'Token tokenized as '.$opener['type'].', not T_OPEN_PARENTHESIS (code)'); + + if ($owner !== false) { + $this->assertArrayHasKey('parenthesis_owner', $opener, 'Parenthesis owner is not set'); + $this->assertSame(($openPtr + $owner), $opener['parenthesis_owner'], 'Opener parenthesis owner is not the expected token'); + } else { + $this->assertArrayNotHasKey('parenthesis_owner', $opener, 'Parenthesis owner is set'); + } + + $this->assertArrayHasKey('parenthesis_opener', $opener, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $opener, 'Parenthesis closer is not set'); + $this->assertSame($openPtr, $opener['parenthesis_opener'], 'Parenthesis opener is not the expected token'); + + $closePtr = $opener['parenthesis_closer']; + $closer = $tokens[$closePtr]; + + // Make sure we're looking at the right token. + $this->assertSame(T_CLOSE_PARENTHESIS, $closer['code'], 'Token tokenized as '.$closer['type'].', not T_CLOSE_PARENTHESIS (code)'); + + if ($owner !== false) { + $this->assertArrayHasKey('parenthesis_owner', $closer, 'Parenthesis owner is not set'); + $this->assertSame(($openPtr + $owner), $closer['parenthesis_owner'], 'Closer parenthesis owner is not the expected token'); + } else { + $this->assertArrayNotHasKey('parenthesis_owner', $closer, 'Parenthesis owner is set'); + } + + $this->assertArrayHasKey('parenthesis_opener', $closer, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $closer, 'Parenthesis closer is not set'); + $this->assertSame($closePtr, $closer['parenthesis_closer'], 'Parenthesis closer is not the expected token'); + + for ($i = ($openPtr + 1); $i < $closePtr; $i++) { + $this->assertArrayHasKey('nested_parenthesis', $tokens[$i], "Nested parenthesis key not set on token $i ({$tokens[$i]['type']})"); + $this->assertArrayHasKey($openPtr, $tokens[$i]['nested_parenthesis'], 'Nested parenthesis is missing target parentheses set'); + $this->assertSame($closePtr, $tokens[$i]['nested_parenthesis'][$openPtr], 'Nested parenthesis closer not set correctly'); + } + + }//end testNormalParentheses() + + + /** + * Data provider. + * + * @see testNormalParentheses() + * + * @return array> + */ + public static function dataNormalParentheses() + { + // "Owner" offsets are relative to the open parenthesis. + return [ + 'parens without owner' => [ + 'testMarker' => '/* testParensNoOwner */', + ], + 'parens without owner in ternary then' => [ + 'testMarker' => '/* testParensNoOwnerInTernary */', + ], + 'parens without owner in short ternary' => [ + 'testMarker' => '/* testParensNoOwnerInShortTernary */', + ], + 'parens with owner: function; & in default value' => [ + 'testMarker' => '/* testParensOwnerFunctionAmpersandInDefaultValue */', + 'owner' => -3, + ], + 'parens with owner: closure; param declared by & ref' => [ + 'testMarker' => '/* testParensOwnerClosureAmpersandParamRef */', + 'owner' => -1, + ], + 'parens with owner: if' => [ + 'testMarker' => '/* testParensOwnerIf */', + 'owner' => -2, + ], + 'parens without owner in if condition' => [ + 'testMarker' => '/* testParensNoOwnerInIfCondition */', + ], + 'parens with owner: for' => [ + 'testMarker' => '/* testParensOwnerFor */', + 'owner' => -2, + ], + 'parens without owner in for condition' => [ + 'testMarker' => '/* testParensNoOwnerInForCondition */', + ], + 'parens with owner: match' => [ + 'testMarker' => '/* testParensOwnerMatch */', + 'owner' => -1, + ], + 'parens with owner: array' => [ + 'testMarker' => '/* testParensOwnerArray */', + 'owner' => -2, + ], + 'parens without owner in array; function call with & in callable' => [ + 'testMarker' => '/* testParensNoOwnerFunctionCallWithAmpersandInCallable */', + ], + 'parens with owner: fn; & in return value' => [ + 'testMarker' => '/* testParensOwnerArrowFn */', + 'owner' => -1, + ], + 'parens with owner: list with reference vars' => [ + 'testMarker' => '/* testParensOwnerListWithRefVars */', + 'owner' => -1, + ], + 'parens without owner, function call with DNF look-a-like param' => [ + 'testMarker' => '/* testParensNoOwnerFunctionCallwithDNFLookALikeParam */', + ], + + 'parens without owner in OO const default value' => [ + 'testMarker' => '/* testParensNoOwnerOOConstDefaultValue */', + ], + 'parens without owner in property default 1' => [ + 'testMarker' => '/* testParensNoOwnerPropertyDefaultValue1 */', + ], + 'parens without owner in property default 2' => [ + 'testMarker' => '/* testParensNoOwnerPropertyDefaultValue2 */', + ], + 'parens without owner in param default value' => [ + 'testMarker' => '/* testParensNoOwnerParamDefaultValue */', + ], + 'parens without owner in return statement 1' => [ + 'testMarker' => '/* testParensNoOwnerInReturnValue1 */', + ], + 'parens without owner in return statement 2' => [ + 'testMarker' => '/* testParensNoOwnerInReturnValue2 */', + ], + 'parens without owner in return statement 3' => [ + 'testMarker' => '/* testParensNoOwnerInReturnValue3 */', + ], + 'parens with owner: closure; & in default value' => [ + 'testMarker' => '/* testParensOwnerClosureAmpersandInDefaultValue */', + 'owner' => -2, + ], + 'parens with owner: fn; dnf used within' => [ + 'testMarker' => '/* testParensOwnerArrowDNFUsedWithin */', + 'owner' => -2, + ], + 'parens without owner: default value for param in arrow function' => [ + 'testMarker' => '/* testParensNoOwnerAmpersandInDefaultValue */', + ], + 'parens without owner in arrow function return expression' => [ + 'testMarker' => '/* testParensNoOwnerInArrowReturnExpression */', + ], + ]; + + }//end dataNormalParentheses() + + + /** + * Test that parentheses when used in a DNF type declaration are correctly tokenized. + * + * Includes verifying that: + * - the tokens between the parentheses all have a "nested_parenthesis" key. + * - all ampersands between the parentheses are tokenized as T_TYPE_INTERSECTION. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataDNFTypeParentheses + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createParenthesisNestingMap + * + * @return void + */ + public function testDNFTypeParentheses($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + + $openPtr = $this->getTargetToken($testMarker, [T_OPEN_PARENTHESIS, T_TYPE_OPEN_PARENTHESIS]); + $opener = $tokens[$openPtr]; + + // Make sure we're looking at the right token. + $this->assertSame(T_TYPE_OPEN_PARENTHESIS, $opener['code'], 'Token tokenized as '.$opener['type'].', not T_TYPE_OPEN_PARENTHESIS (code)'); + + $this->assertArrayNotHasKey('parenthesis_owner', $opener, 'Parenthesis owner is set'); + $this->assertArrayHasKey('parenthesis_opener', $opener, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $opener, 'Parenthesis closer is not set'); + $this->assertSame($openPtr, $opener['parenthesis_opener'], 'Parenthesis opener is not the expected token'); + + $closePtr = $opener['parenthesis_closer']; + $closer = $tokens[$closePtr]; + + // Make sure we're looking at the right token. + $this->assertSame(T_TYPE_CLOSE_PARENTHESIS, $closer['code'], 'Token tokenized as '.$closer['type'].', not T_TYPE_CLOSE_PARENTHESIS (code)'); + + $this->assertArrayNotHasKey('parenthesis_owner', $closer, 'Parenthesis owner is set'); + $this->assertArrayHasKey('parenthesis_opener', $closer, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $closer, 'Parenthesis closer is not set'); + $this->assertSame($closePtr, $closer['parenthesis_closer'], 'Parenthesis closer is not the expected token'); + + $intersectionCount = 0; + for ($i = ($openPtr + 1); $i < $closePtr; $i++) { + $this->assertArrayHasKey('nested_parenthesis', $tokens[$i], "Nested parenthesis key not set on token $i ({$tokens[$i]['type']})"); + $this->assertArrayHasKey($openPtr, $tokens[$i]['nested_parenthesis'], 'Nested parenthesis is missing target parentheses set'); + $this->assertSame($closePtr, $tokens[$i]['nested_parenthesis'][$openPtr], 'Nested parenthesis closer not set correctly'); + }//end for + + }//end testDNFTypeParentheses() + + + /** + * Data provider. + * + * @see testDNFTypeParentheses() + * + * @return array> + */ + public static function dataDNFTypeParentheses() + { + return [ + 'OO const type: unqualified classes' => [ + 'testMarker' => '/* testDNFTypeOOConstUnqualifiedClasses */', + ], + 'OO const type: modifiers in reverse order' => [ + 'testMarker' => '/* testDNFTypeOOConstReverseModifierOrder */', + ], + 'OO const type: multi-dnf part 1' => [ + 'testMarker' => '/* testDNFTypeOOConstMulti1 */', + ], + 'OO const type: multi-dnf part 2' => [ + 'testMarker' => '/* testDNFTypeOOConstMulti2 */', + ], + 'OO const type: multi-dnf part 3' => [ + 'testMarker' => '/* testDNFTypeOOConstMulti3 */', + ], + 'OO const type: namespace relative classes' => [ + 'testMarker' => '/* testDNFTypeOOConstNamespaceRelative */', + ], + 'OO const type: partially qualified classes' => [ + 'testMarker' => '/* testDNFTypeOOConstPartiallyQualified */', + ], + 'OO const type: fully qualified classes' => [ + 'testMarker' => '/* testDNFTypeOOConstFullyQualified */', + ], + + 'OO property type: unqualified classes' => [ + 'testMarker' => '/* testDNFTypePropertyUnqualifiedClasses */', + ], + 'OO property type: modifiers in reverse order' => [ + 'testMarker' => '/* testDNFTypePropertyReverseModifierOrder */', + ], + 'OO property type: multi-dnf namespace relative classes' => [ + 'testMarker' => '/* testDNFTypePropertyMultiNamespaceRelative */', + ], + 'OO property type: multi-dnf partially qualified classes' => [ + 'testMarker' => '/* testDNFTypePropertyMultiPartiallyQualified */', + ], + 'OO property type: multi-dnf fully qualified classes' => [ + 'testMarker' => '/* testDNFTypePropertyMultiFullyQualified */', + ], + + 'OO property type: multi-dnf with readonly keyword 1' => [ + 'testMarker' => '/* testDNFTypePropertyWithReadOnlyKeyword1 */', + ], + 'OO property type: multi-dnf with readonly keyword 2' => [ + 'testMarker' => '/* testDNFTypePropertyWithReadOnlyKeyword2 */', + ], + 'OO property type: with static and readonly keywords' => [ + 'testMarker' => '/* testDNFTypePropertyWithStaticAndReadOnlyKeywords */', + ], + 'OO property type: with only static keyword' => [ + 'testMarker' => '/* testDNFTypePropertyWithOnlyStaticKeyword */', + ], + 'OO method param type: first param' => [ + 'testMarker' => '/* testDNFTypeParam1WithAttribute */', + ], + 'OO method param type: second param, first DNF' => [ + 'testMarker' => '/* testDNFTypeParam2 */', + ], + 'OO method param type: second param, second DNF' => [ + 'testMarker' => '/* testDNFTypeParam3 */', + ], + 'OO method param type: namespace relative classes' => [ + 'testMarker' => '/* testDNFTypeParamNamespaceRelative */', + ], + 'OO method param type: partially qualified classes' => [ + 'testMarker' => '/* testDNFTypeParamPartiallyQualified */', + ], + 'OO method param type: fully qualified classes' => [ + 'testMarker' => '/* testDNFTypeParamFullyQualified */', + ], + 'Constructor property promotion with multi DNF 1' => [ + 'testMarker' => '/* testDNFTypeConstructorPropertyPromotion1 */', + ], + 'Constructor property promotion with multi DNF 2' => [ + 'testMarker' => '/* testDNFTypeConstructorPropertyPromotion2 */', + ], + 'OO method return type: multi DNF 1' => [ + 'testMarker' => '/* testDNFTypeReturnType1 */', + ], + 'OO method return type: multi DNF 2' => [ + 'testMarker' => '/* testDNFTypeReturnType2 */', + ], + 'OO abstract method return type: multi DNF 1' => [ + 'testMarker' => '/* testDNFTypeAbstractMethodReturnType1 */', + ], + 'OO abstract method return type: multi DNF 2' => [ + 'testMarker' => '/* testDNFTypeAbstractMethodReturnType2 */', + ], + 'OO method return type: namespace relative classes' => [ + 'testMarker' => '/* testDNFTypeReturnTypeNamespaceRelative */', + ], + 'OO method return type: partially qualified classes' => [ + 'testMarker' => '/* testDNFTypeReturnPartiallyQualified */', + ], + 'OO method return type: fully qualified classes' => [ + 'testMarker' => '/* testDNFTypeReturnFullyQualified */', + ], + 'function param type: with reference' => [ + 'testMarker' => '/* testDNFTypeWithReference */', + ], + 'function param type: with spread' => [ + 'testMarker' => '/* testDNFTypeWithSpreadOperator */', + ], + 'closure param type: with illegal nullable' => [ + 'testMarker' => '/* testDNFTypeClosureParamIllegalNullable */', + ], + 'closure return type' => [ + 'testMarker' => '/* testDNFTypeClosureReturn */', + ], + 'arrow function param type' => [ + 'testMarker' => '/* testDNFTypeArrowParam */', + ], + 'arrow function return type' => [ + 'testMarker' => '/* testDNFTypeArrowReturnType */', + ], + 'arrow function param type with return by ref' => [ + 'testMarker' => '/* testDNFTypeArrowParamWithReturnByRef */', + ], + + 'illegal syntax: unnecessary parentheses (no union)' => [ + 'testMarker' => '/* testDNFTypeParamIllegalUnnecessaryParens */', + ], + 'illegal syntax: union within parentheses, intersect outside' => [ + 'testMarker' => '/* testDNFTypeParamIllegalIntersectUnionReversed */', + ], + 'illegal syntax: nested parentheses' => [ + 'testMarker' => '/* testDNFTypeParamIllegalNestedParens */', + ], + ]; + + }//end dataDNFTypeParentheses() + + +}//end class diff --git a/tests/Core/Tokenizer/Tokenizer/CreateTokenMapArrayParenthesesTest.inc b/tests/Core/Tokenizer/Tokenizer/CreateTokenMapArrayParenthesesTest.inc new file mode 100644 index 0000000000..6d8adfcbae --- /dev/null +++ b/tests/Core/Tokenizer/Tokenizer/CreateTokenMapArrayParenthesesTest.inc @@ -0,0 +1,58 @@ + 10); + +/* testArrayWithComment */ +$var = Array /*comment*/ (1 => 10); + +/* testNestingArray */ +$var = array( + /* testNestedArray */ + array( + 'key' => 'value', + + /* testClosureReturnType */ + 'closure' => function($a) use($global) : Array {}, + ), +); + +/* testFunctionDeclarationParamType */ +function typedParam(array $a) {} + +/* testFunctionDeclarationReturnType */ +function returnType($a) : int|array|null {} + +class Bar { + /* testClassConst */ + const ARRAY = []; + + /* testClassMethod */ + public function array() {} + + /* testOOConstType */ + const array /* testTypedOOConstName */ ARRAY = /* testOOConstDefault */ array(); + + /* testOOPropertyType */ + protected array $property; +} + +class DNFTypes { + /* testOOConstDNFType */ + const (A&B)|array|(C&D) NAME = []; + + /* testOOPropertyDNFType */ + protected (A&B)|ARRAY|null $property; + + /* testFunctionDeclarationParamDNFType */ + public function name(null|array|(A&B) $param) { + /* testClosureDeclarationParamDNFType */ + $cl = function ( array|(A&B) $param) {}; + + /* testArrowDeclarationReturnDNFType */ + $arrow = fn($a): (A&B)|Array => new $a; + } +} diff --git a/tests/Core/Tokenizer/Tokenizer/CreateTokenMapArrayParenthesesTest.php b/tests/Core/Tokenizer/Tokenizer/CreateTokenMapArrayParenthesesTest.php new file mode 100644 index 0000000000..e362448c9d --- /dev/null +++ b/tests/Core/Tokenizer/Tokenizer/CreateTokenMapArrayParenthesesTest.php @@ -0,0 +1,212 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; + +final class CreateTokenMapArrayParenthesesTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that the array keyword is correctly tokenized as `T_ARRAY`. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent Optional. The token content to look for. + * + * @dataProvider dataArrayKeyword + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap + * + * @return void + */ + public function testArrayKeyword($testMarker, $testContent='array') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + // Make sure we're looking at the right token. + $this->assertSame(T_ARRAY, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_ARRAY (code)'); + + $this->assertArrayHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is not set'); + $this->assertArrayHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is not set'); + + }//end testArrayKeyword() + + + /** + * Data provider. + * + * @see testArrayKeyword() + * + * @return array> + */ + public static function dataArrayKeyword() + { + return [ + 'empty array' => [ + 'testMarker' => '/* testEmptyArray */', + ], + 'array with space before parenthesis' => [ + 'testMarker' => '/* testArrayWithSpace */', + ], + 'array with comment before parenthesis' => [ + 'testMarker' => '/* testArrayWithComment */', + 'testContent' => 'Array', + ], + 'nested: outer array' => [ + 'testMarker' => '/* testNestingArray */', + ], + 'nested: inner array' => [ + 'testMarker' => '/* testNestedArray */', + ], + 'OO constant default value' => [ + 'testMarker' => '/* testOOConstDefault */', + ], + ]; + + }//end dataArrayKeyword() + + + /** + * Test that the array keyword when used in a type declaration is correctly tokenized as `T_STRING`. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent Optional. The token content to look for. + * + * @dataProvider dataArrayType + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap + * + * @return void + */ + public function testArrayType($testMarker, $testContent='array') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + // Make sure we're looking at the right token. + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + }//end testArrayType() + + + /** + * Data provider. + * + * @see testArrayType() + * + * @return array> + */ + public static function dataArrayType() + { + return [ + 'closure return type' => [ + 'testMarker' => '/* testClosureReturnType */', + 'testContent' => 'Array', + ], + 'function param type' => [ + 'testMarker' => '/* testFunctionDeclarationParamType */', + ], + 'function union return type' => [ + 'testMarker' => '/* testFunctionDeclarationReturnType */', + ], + 'OO constant type' => [ + 'testMarker' => '/* testOOConstType */', + ], + 'OO property type' => [ + 'testMarker' => '/* testOOPropertyType */', + ], + + 'OO constant DNF type' => [ + 'testMarker' => '/* testOOConstDNFType */', + ], + 'OO property DNF type' => [ + 'testMarker' => '/* testOOPropertyDNFType */', + 'testContent' => 'ARRAY', + ], + 'function param DNF type' => [ + 'testMarker' => '/* testFunctionDeclarationParamDNFType */', + ], + 'closure param DNF type' => [ + 'testMarker' => '/* testClosureDeclarationParamDNFType */', + ], + 'arrow return DNF type' => [ + 'testMarker' => '/* testArrowDeclarationReturnDNFType */', + 'testContent' => 'Array', + ], + ]; + + }//end dataArrayType() + + + /** + * Verify that the retokenization of `T_ARRAY` tokens to `T_STRING` is handled correctly + * for tokens with the contents 'array' which aren't in actual fact the array keyword. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotArrayKeyword + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap + * + * @return void + */ + public function testNotArrayKeyword($testMarker, $testContent='array') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + // Make sure we're looking at the right token. + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + }//end testNotArrayKeyword() + + + /** + * Data provider. + * + * @see testNotArrayKeyword() + * + * @return array> + */ + public static function dataNotArrayKeyword() + { + return [ + 'class-constant-name' => [ + 'testMarker' => '/* testClassConst */', + 'testContent' => 'ARRAY', + ], + 'class-method-name' => [ + 'testMarker' => '/* testClassMethod */', + ], + 'class-constant-name-after-type' => [ + 'testMarker' => '/* testTypedOOConstName */', + 'testContent' => 'ARRAY', + ], + ]; + + }//end dataNotArrayKeyword() + + +}//end class diff --git a/tests/Core/Tokenizer/HeredocNowdocCloserTest.inc b/tests/Core/Tokenizer/Tokenizer/HeredocNowdocCloserTest.inc similarity index 100% rename from tests/Core/Tokenizer/HeredocNowdocCloserTest.inc rename to tests/Core/Tokenizer/Tokenizer/HeredocNowdocCloserTest.inc diff --git a/tests/Core/Tokenizer/HeredocNowdocCloserTest.php b/tests/Core/Tokenizer/Tokenizer/HeredocNowdocCloserTest.php similarity index 96% rename from tests/Core/Tokenizer/HeredocNowdocCloserTest.php rename to tests/Core/Tokenizer/Tokenizer/HeredocNowdocCloserTest.php index d43768f0e4..a2357db8ae 100644 --- a/tests/Core/Tokenizer/HeredocNowdocCloserTest.php +++ b/tests/Core/Tokenizer/Tokenizer/HeredocNowdocCloserTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; /** * Heredoc/nowdoc closer token test. diff --git a/tests/Core/Tokenizer/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc b/tests/Core/Tokenizer/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc new file mode 100644 index 0000000000..13b87242e1 --- /dev/null +++ b/tests/Core/Tokenizer/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc @@ -0,0 +1,95 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; + +final class RecurseScopeMapCaseKeywordConditionsTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that the enum "case" is converted to T_ENUM_CASE. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataEnumCases + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testEnumCases($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $enumCase = $this->getTargetToken($testMarker, [T_ENUM_CASE, T_CASE]); + $tokenArray = $tokens[$enumCase]; + + // Make sure we're looking at the right token. + $this->assertSame(T_ENUM_CASE, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_ENUM_CASE (code)'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + + }//end testEnumCases() + + + /** + * Data provider. + * + * @see testEnumCases() + * + * @return array> + */ + public static function dataEnumCases() + { + return [ + 'enum case, no value' => ['/* testPureEnumCase */'], + 'enum case, integer value' => ['/* testBackingIntegerEnumCase */'], + 'enum case, string value' => ['/* testBackingStringEnumCase */'], + 'enum case, integer value in more complex enum' => ['/* testEnumCaseInComplexEnum */'], + 'enum case, keyword in mixed case' => ['/* testEnumCaseIsCaseInsensitive */'], + 'enum case, after switch statement' => ['/* testEnumCaseAfterSwitch */'], + 'enum case, after switch statement using alternative syntax' => ['/* testEnumCaseAfterSwitchWithEndSwitch */'], + ]; + + }//end dataEnumCases() + + + /** + * Test that "case" that is not enum case is still tokenized as `T_CASE`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataNotEnumCases + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testNotEnumCases($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $case = $this->getTargetToken($testMarker, [T_ENUM_CASE, T_CASE]); + $tokenArray = $tokens[$case]; + + // Make sure we're looking at the right token. + $this->assertSame(T_CASE, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_CASE (code)'); + + $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokenArray, 'Scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokenArray, 'Scope closer is not set'); + + }//end testNotEnumCases() + + + /** + * Data provider. + * + * @see testNotEnumCases() + * + * @return array> + */ + public static function dataNotEnumCases() + { + return [ + 'switch case with constant, semicolon condition end' => ['/* testCaseWithSemicolonIsNotEnumCase */'], + 'switch case with constant, colon condition end' => ['/* testCaseWithConstantIsNotEnumCase */'], + 'switch case with constant, comparison' => ['/* testCaseWithConstantAndIdenticalIsNotEnumCase */'], + 'switch case with constant, assignment' => ['/* testCaseWithAssigmentToConstantIsNotEnumCase */'], + 'switch case with constant, keyword in mixed case' => ['/* testIsNotEnumCaseIsCaseInsensitive */'], + 'switch case, body in curlies declares enum' => ['/* testCaseInSwitchWhenCreatingEnumInSwitch1 */'], + 'switch case, body after semicolon declares enum' => ['/* testCaseInSwitchWhenCreatingEnumInSwitch2 */'], + ]; + + }//end dataNotEnumCases() + + + /** + * Test that "case" that is not enum case is still tokenized as `T_CASE`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataKeywordAsEnumCaseNameShouldBeString + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testKeywordAsEnumCaseNameShouldBeString($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $enumCaseName = $this->getTargetToken($testMarker, [T_STRING, T_INTERFACE, T_TRAIT, T_ENUM, T_FUNCTION, T_FALSE, T_DEFAULT, T_ARRAY]); + $tokenArray = $tokens[$enumCaseName]; + + // Make sure we're looking at the right token. + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + + }//end testKeywordAsEnumCaseNameShouldBeString() + + + /** + * Data provider. + * + * @see testKeywordAsEnumCaseNameShouldBeString() + * + * @return array> + */ + public static function dataKeywordAsEnumCaseNameShouldBeString() + { + return [ + '"interface" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString1 */'], + '"trait" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString2 */'], + '"enum" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString3 */'], + '"function" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString4 */'], + '"false" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString5 */'], + '"default" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString6 */'], + '"array" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString7 */'], + ]; + + }//end dataKeywordAsEnumCaseNameShouldBeString() + + +}//end class diff --git a/tests/Core/Tokenizer/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.inc b/tests/Core/Tokenizer/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.inc new file mode 100644 index 0000000000..648149d2ff --- /dev/null +++ b/tests/Core/Tokenizer/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.inc @@ -0,0 +1,203 @@ + 1, + 2 => 2, + /* testSimpleMatchDefault */ + default => 'default', + }; +} + +function switchWithDefault($i) { + switch ($i) { + case 1: + return 1; + case 2: + return 2; + /* testSimpleSwitchDefault */ + default: + return 'default'; + } +} + +function switchWithDefaultAndCurlies($i) { + switch ($i) { + case 1: + return 1; + case 2: + return 2; + /* testSimpleSwitchDefaultWithCurlies */ + default: { + return 'default'; + } + } +} + +function matchWithDefaultInSwitch() { + switch ($something) { + case 'foo': + $var = [1, 2, 3]; + $var = match ($i) { + 1 => 1, + /* testMatchDefaultNestedInSwitchCase1 */ + default => 'default', + }; + continue; + + case 'bar' : + $i = callMe($a, $b); + return match ($i) { + 1 => 1, + /* testMatchDefaultNestedInSwitchCase2 */ + default => 'default', + }; + + /* testSwitchDefault */ + default; + echo 'something', match ($i) { + 1, => 1, + /* testMatchDefaultNestedInSwitchDefault */ + default, => 'default', + }; + break; + } +} + +function switchWithDefaultInMatch() { + $x = match ($y) { + 5, 8 => function($z) { + switch($z) { + case 'a'; + $var = [1, 2, 3]; + return 'a'; + /* testSwitchDefaultNestedInMatchCase */ + default: + $var = [1, 2, 3]; + return 'default1'; + } + }, + /* testMatchDefault */ + default => function($z) { + switch($z) { + case 'a': + $i = callMe($a, $b); + return 'b'; + /* testSwitchDefaultNestedInMatchDefault */ + default: + $i = callMe($a, $b); + return 'default2'; + } + } + }; +} + +function shortArrayWithConstantKey() { + $arr = [ + /* testClassConstantAsShortArrayKey */ + SomeClass::DEFAULT => 1, + /* testClassPropertyAsShortArrayKey */ + SomeClass->DEFAULT => 1, + /* testNamespacedConstantAsShortArrayKey */ + // Intentional parse error PHP < 8.0. Reserved keyword used as namespaced constant. + SomeNamespace\DEFAULT => 1, + /* testFQNGlobalConstantAsShortArrayKey */ + // Intentional parse error in PHP < 8.0. Reserved keyword used as global constant. + \DEFAULT => 1, + ]; +} + +function longArrayWithConstantKey() { + $arr = array( + /* testClassConstantAsLongArrayKey */ + SomeClass::DEFAULT => 1, + ); +} + +function yieldWithConstantKey() { + /* testClassConstantAsYieldKey */ + yield SomeClass::DEFAULT => 1; +} + +function longArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchDefaultWithNestedLongArrayWithClassConstantKey */ + DEFAULT => array( + /* testClassConstantAsLongArrayKeyNestedInMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultWithNestedLongArrayWithClassConstantKeyLevelDown */ + DEFAULT => array( + /* testClassConstantAsLongArrayKeyNestedInMatchLevelDown */ + SomeClass::DEFAULT => 1, + ), + }, + ), + }; +} + +function shortArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchDefaultWithNestedShortArrayWithClassConstantKey */ + DEFAULT => [ + /* testClassConstantAsShortArrayKeyNestedInMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultWithNestedShortArrayWithClassConstantKeyLevelDown */ + DEFAULT => [ + /* testClassConstantAsShortArrayKeyNestedInMatchLevelDown */ + SomeClass::DEFAULT => 1, + ], + }, + ], + }; +} + + +function longArrayWithConstantKeyWithNestedMatch() { + return array( + /* testClassConstantAsLongArrayKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultNestedInLongArray */ + DEFAULT => 'foo' + }, + ); +} + +function shortArrayWithConstantKeyWithNestedMatch() { + return [ + /* testClassConstantAsShortArrayKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultNestedInShortArray */ + DEFAULT => 'foo' + }, + ]; +} + +function switchWithConstantNonDefault($i) { + switch ($i) { + /* testClassConstantInSwitchCase */ + case SomeClass::DEFAULT: + return 1; + + /* testClassPropertyInSwitchCase */ + case SomeClass->DEFAULT: + return 2; + + /* testNamespacedConstantInSwitchCase */ + // Intentional parse error PHP < 8.0. Reserved keyword used as constant. + case SomeNamespace\DEFAULT: + return 2; + + /* testNamespaceRelativeConstantInSwitchCase */ + // Intentional parse error PHP < 8.0. Reserved keyword used as global constant. + case namespace\DEFAULT: + return 2; + } +} + +class Foo { + /* testClassConstant */ + const DEFAULT = 'foo'; + + /* testMethodDeclaration */ + public function default() {} +} diff --git a/tests/Core/Tokenizer/DefaultKeywordTest.php b/tests/Core/Tokenizer/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.php similarity index 95% rename from tests/Core/Tokenizer/DefaultKeywordTest.php rename to tests/Core/Tokenizer/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.php index cee3d263de..fb3a76afbf 100644 --- a/tests/Core/Tokenizer/DefaultKeywordTest.php +++ b/tests/Core/Tokenizer/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.php @@ -8,9 +8,11 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\Tokenizer; -final class DefaultKeywordTest extends AbstractTokenizerTestCase +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; + +final class RecurseScopeMapDefaultKeywordConditionsTest extends AbstractTokenizerTestCase { @@ -24,7 +26,6 @@ final class DefaultKeywordTest extends AbstractTokenizerTestCase * @param string $testContent The token content to look for. * * @dataProvider dataMatchDefault - * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap * * @return void @@ -36,8 +37,8 @@ public function testMatchDefault($testMarker, $testContent='default') $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); $tokenArray = $tokens[$token]; + // Make sure we're looking at the right token. $this->assertSame(T_MATCH_DEFAULT, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_DEFAULT (code)'); - $this->assertSame('T_MATCH_DEFAULT', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_DEFAULT (type)'); $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); @@ -128,8 +129,8 @@ public function testSwitchDefault($testMarker, $openerOffset, $closerOffset, $co $expectedScopeOpener = ($token + $openerOffset); $expectedScopeCloser = ($token + $closerOffset); + // Make sure we're looking at the right token. $this->assertSame(T_DEFAULT, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_DEFAULT (code)'); - $this->assertSame('T_DEFAULT', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_DEFAULT (type)'); $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition is not set'); $this->assertArrayHasKey('scope_opener', $tokenArray, 'Scope opener is not set'); @@ -226,7 +227,7 @@ public static function dataSwitchDefault() * @param string $testContent The token content to look for. * * @dataProvider dataNotDefaultKeyword - * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap * * @return void */ @@ -237,8 +238,8 @@ public function testNotDefaultKeyword($testMarker, $testContent='DEFAULT') $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); $tokenArray = $tokens[$token]; + // Make sure we're looking at the right token. $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); - $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); @@ -325,7 +326,6 @@ public static function dataNotDefaultKeyword() * * @link https://github.com/squizlabs/PHP_CodeSniffer/issues/3326 * - * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap * * @return void diff --git a/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc b/tests/Core/Tokenizer/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc similarity index 100% rename from tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc rename to tests/Core/Tokenizer/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc diff --git a/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php b/tests/Core/Tokenizer/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php similarity index 97% rename from tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php rename to tests/Core/Tokenizer/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php index 5359b7282d..dba98cdb02 100644 --- a/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php +++ b/tests/Core/Tokenizer/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php @@ -7,7 +7,9 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Tokenizer; +namespace PHP_CodeSniffer\Tests\Core\Tokenizer\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizer\AbstractTokenizerTestCase; final class ScopeSettingWithNamespaceOperatorTest extends AbstractTokenizerTestCase {