Skip to content

Commit bbb8dd3

Browse files
committed
Merge branch 'feature/php8-tokenizer-magic-constant-dereferencing' of https://github.com/jrfnl/PHP_CodeSniffer
2 parents 4eb94f8 + a1a7e70 commit bbb8dd3

File tree

5 files changed

+247
-0
lines changed

5 files changed

+247
-0
lines changed

package.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
113113
<file baseinstalldir="" name="BackfillFnTokenTest.php" role="test" />
114114
<file baseinstalldir="" name="BackfillNumericSeparatorTest.inc" role="test" />
115115
<file baseinstalldir="" name="BackfillNumericSeparatorTest.php" role="test" />
116+
<file baseinstalldir="" name="ShortArrayTest.inc" role="test" />
117+
<file baseinstalldir="" name="ShortArrayTest.php" role="test" />
116118
</dir>
117119
<file baseinstalldir="" name="AbstractMethodUnitTest.php" role="test" />
118120
<file baseinstalldir="" name="AllTests.php" role="test" />
@@ -1977,6 +1979,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
19771979
<install as="CodeSniffer/Core/Tokenizer/BackfillFnTokenTest.inc" name="tests/Core/Tokenizer/BackfillFnTokenTest.inc" />
19781980
<install as="CodeSniffer/Core/Tokenizer/BackfillNumericSeparatorTest.php" name="tests/Core/Tokenizer/BackfillNumericSeparatorTest.php" />
19791981
<install as="CodeSniffer/Core/Tokenizer/BackfillNumericSeparatorTest.inc" name="tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc" />
1982+
<install as="CodeSniffer/Core/Tokenizer/ShortArrayTest.php" name="tests/Core/Tokenizer/ShortArrayTest.php" />
1983+
<install as="CodeSniffer/Core/Tokenizer/ShortArrayTest.inc" name="tests/Core/Tokenizer/ShortArrayTest.inc" />
19801984
<install as="CodeSniffer/Standards/AllSniffs.php" name="tests/Standards/AllSniffs.php" />
19811985
<install as="CodeSniffer/Standards/AbstractSniffUnitTest.php" name="tests/Standards/AbstractSniffUnitTest.php" />
19821986
</filelist>
@@ -2030,6 +2034,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
20302034
<install as="CodeSniffer/Core/Tokenizer/BackfillFnTokenTest.inc" name="tests/Core/Tokenizer/BackfillFnTokenTest.inc" />
20312035
<install as="CodeSniffer/Core/Tokenizer/BackfillNumericSeparatorTest.php" name="tests/Core/Tokenizer/BackfillNumericSeparatorTest.php" />
20322036
<install as="CodeSniffer/Core/Tokenizer/BackfillNumericSeparatorTest.inc" name="tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc" />
2037+
<install as="CodeSniffer/Core/Tokenizer/ShortArrayTest.php" name="tests/Core/Tokenizer/ShortArrayTest.php" />
2038+
<install as="CodeSniffer/Core/Tokenizer/ShortArrayTest.inc" name="tests/Core/Tokenizer/ShortArrayTest.inc" />
20332039
<install as="CodeSniffer/Standards/AllSniffs.php" name="tests/Standards/AllSniffs.php" />
20342040
<install as="CodeSniffer/Standards/AbstractSniffUnitTest.php" name="tests/Standards/AbstractSniffUnitTest.php" />
20352041
<ignore name="bin/phpcs.bat" />

src/Tokenizers/PHP.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,6 +1974,7 @@ protected function processAdditional()
19741974
T_STRING => T_STRING,
19751975
T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING,
19761976
];
1977+
$allowed += Util\Tokens::$magicConstants;
19771978

19781979
for ($x = ($i - 1); $x >= 0; $x--) {
19791980
// If we hit a scope opener, the statement has ended

src/Util/Tokens.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,24 @@ final class Tokens
589589
T_TRAIT => T_TRAIT,
590590
];
591591

592+
/**
593+
* Tokens representing PHP magic constants.
594+
*
595+
* @var array <int|string> => <int|string>
596+
*
597+
* @link https://www.php.net/language.constants.predefined PHP Manual on magic constants
598+
*/
599+
public static $magicConstants = [
600+
T_CLASS_C => T_CLASS_C,
601+
T_DIR => T_DIR,
602+
T_FILE => T_FILE,
603+
T_FUNC_C => T_FUNC_C,
604+
T_LINE => T_LINE,
605+
T_METHOD_C => T_METHOD_C,
606+
T_NS_C => T_NS_C,
607+
T_TRAIT_C => T_TRAIT_C,
608+
];
609+
592610

593611
/**
594612
* Given a token, returns the name of the token.
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
/*
4+
* Square brackets.
5+
*/
6+
7+
/* testArrayAccess1 */
8+
$var = $array[10];
9+
10+
$var = $array[++$y]/* testArrayAccess2 */[$x];
11+
12+
/* testArrayAssignment */
13+
$array[] = $var;
14+
15+
/* testFunctionCallDereferencing */
16+
$var = function_call()[$x];
17+
18+
/* testMethodCallDereferencing */
19+
$var = $obj->function_call()[$x];
20+
21+
/* testStaticMethodCallDereferencing */
22+
$var = ClassName::function_call()[$x];
23+
24+
/* testPropertyDereferencing */
25+
$var = $obj->property[2];
26+
27+
/* testPropertyDereferencingWithInaccessibleName */
28+
$var = $ref->{'ref-type'}[1];
29+
30+
/* testStaticPropertyDereferencing */
31+
$var ClassName::$property[2];
32+
33+
/* testStringDereferencing */
34+
$var = 'PHP'[1];
35+
36+
/* testStringDereferencingDoubleQuoted */
37+
$var = "PHP"[$y];
38+
39+
/* testConstantDereferencing */
40+
$var = MY_CONSTANT[1];
41+
42+
/* testClassConstantDereferencing */
43+
$var ClassName::CONSTANT_NAME[2];
44+
45+
/* testMagicConstantDereferencing */
46+
$var = __FILE__[0];
47+
48+
/* testArrayAccessCurlyBraces */
49+
$var = $array{'key'}['key'];
50+
51+
/* testArrayLiteralDereferencing */
52+
echo array(1, 2, 3)[0];
53+
54+
echo [1, 2, 3]/* testShortArrayLiteralDereferencing */[0];
55+
56+
/* testClassMemberDereferencingOnInstantiation1 */
57+
(new foo)[0];
58+
59+
/* testClassMemberDereferencingOnInstantiation2 */
60+
$a = (new Foo( array(1, array(4, 5), 3) ))[1][0];
61+
62+
/* testClassMemberDereferencingOnClone */
63+
echo (clone $iterable)[20];
64+
65+
66+
/*
67+
* Short array brackets.
68+
*/
69+
70+
/* testShortArrayDeclarationEmpty */
71+
$array = [];
72+
73+
/* testShortArrayDeclarationWithOneValue */
74+
$array = [1];
75+
76+
/* testShortArrayDeclarationWithMultipleValues */
77+
$array = [1, 2, 3];
78+
79+
/* testShortArrayDeclarationWithDereferencing */
80+
echo [1, 2, 3][0];
81+
82+
/* testShortListDeclaration */
83+
[ $a, $b ] = $array;
84+
85+
[ $a, $b, /* testNestedListDeclaration */, [$c, $d]] = $array;
86+
87+
/* testArrayWithinFunctionCall */
88+
$var = functionCall([$x, $y]);
89+
90+
/* testLiveCoding */
91+
// Intentional parse error. This has to be the last test in the file.
92+
$array = [
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<?php
2+
/**
3+
* Tests the conversion of square bracket tokens to short array tokens.
4+
*
5+
* @author Juliette Reinders Folmer <phpcs_nospam@adviesenzo.nl>
6+
* @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600)
7+
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8+
*/
9+
10+
namespace PHP_CodeSniffer\Tests\Core\Tokenizer;
11+
12+
use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest;
13+
14+
class ShortArrayTest extends AbstractMethodUnitTest
15+
{
16+
17+
18+
/**
19+
* Test that real square brackets are still tokenized as square brackets.
20+
*
21+
* @param string $testMarker The comment which prefaces the target token in the test file.
22+
*
23+
* @dataProvider dataSquareBrackets
24+
* @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional
25+
*
26+
* @return void
27+
*/
28+
public function testSquareBrackets($testMarker)
29+
{
30+
$tokens = self::$phpcsFile->getTokens();
31+
32+
$opener = $this->getTargetToken($testMarker, [T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY]);
33+
$this->assertSame(T_OPEN_SQUARE_BRACKET, $tokens[$opener]['code']);
34+
$this->assertSame('T_OPEN_SQUARE_BRACKET', $tokens[$opener]['type']);
35+
36+
if (isset($tokens[$opener]['bracket_closer']) === true) {
37+
$closer = $tokens[$opener]['bracket_closer'];
38+
$this->assertSame(T_CLOSE_SQUARE_BRACKET, $tokens[$closer]['code']);
39+
$this->assertSame('T_CLOSE_SQUARE_BRACKET', $tokens[$closer]['type']);
40+
}
41+
42+
}//end testSquareBrackets()
43+
44+
45+
/**
46+
* Data provider.
47+
*
48+
* @see testSquareBrackets()
49+
*
50+
* @return array
51+
*/
52+
public function dataSquareBrackets()
53+
{
54+
return [
55+
['/* testArrayAccess1 */'],
56+
['/* testArrayAccess2 */'],
57+
['/* testArrayAssignment */'],
58+
['/* testFunctionCallDereferencing */'],
59+
['/* testMethodCallDereferencing */'],
60+
['/* testStaticMethodCallDereferencing */'],
61+
['/* testPropertyDereferencing */'],
62+
['/* testPropertyDereferencingWithInaccessibleName */'],
63+
['/* testStaticPropertyDereferencing */'],
64+
['/* testStringDereferencing */'],
65+
['/* testStringDereferencingDoubleQuoted */'],
66+
['/* testConstantDereferencing */'],
67+
['/* testClassConstantDereferencing */'],
68+
['/* testMagicConstantDereferencing */'],
69+
['/* testArrayAccessCurlyBraces */'],
70+
['/* testArrayLiteralDereferencing */'],
71+
['/* testShortArrayLiteralDereferencing */'],
72+
['/* testClassMemberDereferencingOnInstantiation1 */'],
73+
['/* testClassMemberDereferencingOnInstantiation2 */'],
74+
['/* testClassMemberDereferencingOnClone */'],
75+
['/* testLiveCoding */'],
76+
];
77+
78+
}//end dataSquareBrackets()
79+
80+
81+
/**
82+
* Test that short arrays and short lists are still tokenized as short arrays.
83+
*
84+
* @param string $testMarker The comment which prefaces the target token in the test file.
85+
*
86+
* @dataProvider dataShortArrays
87+
* @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional
88+
*
89+
* @return void
90+
*/
91+
public function testShortArrays($testMarker)
92+
{
93+
$tokens = self::$phpcsFile->getTokens();
94+
95+
$opener = $this->getTargetToken($testMarker, [T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY]);
96+
$this->assertSame(T_OPEN_SHORT_ARRAY, $tokens[$opener]['code']);
97+
$this->assertSame('T_OPEN_SHORT_ARRAY', $tokens[$opener]['type']);
98+
99+
if (isset($tokens[$opener]['bracket_closer']) === true) {
100+
$closer = $tokens[$opener]['bracket_closer'];
101+
$this->assertSame(T_CLOSE_SHORT_ARRAY, $tokens[$closer]['code']);
102+
$this->assertSame('T_CLOSE_SHORT_ARRAY', $tokens[$closer]['type']);
103+
}
104+
105+
}//end testShortArrays()
106+
107+
108+
/**
109+
* Data provider.
110+
*
111+
* @see testShortArrays()
112+
*
113+
* @return array
114+
*/
115+
public function dataShortArrays()
116+
{
117+
return [
118+
['/* testShortArrayDeclarationEmpty */'],
119+
['/* testShortArrayDeclarationWithOneValue */'],
120+
['/* testShortArrayDeclarationWithMultipleValues */'],
121+
['/* testShortArrayDeclarationWithDereferencing */'],
122+
['/* testShortListDeclaration */'],
123+
['/* testNestedListDeclaration */'],
124+
['/* testArrayWithinFunctionCall */'],
125+
];
126+
127+
}//end dataShortArrays()
128+
129+
130+
}//end class

0 commit comments

Comments
 (0)