diff --git a/package.xml b/package.xml
index 4d2105b94e..be71b05995 100644
--- a/package.xml
+++ b/package.xml
@@ -113,6 +113,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+
@@ -1977,6 +1979,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+
@@ -2030,6 +2034,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+
diff --git a/src/Tokenizers/PHP.php b/src/Tokenizers/PHP.php
index 2fc86a86d6..84c06a072c 100644
--- a/src/Tokenizers/PHP.php
+++ b/src/Tokenizers/PHP.php
@@ -1973,6 +1973,7 @@ protected function processAdditional()
T_STRING => T_STRING,
T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING,
];
+ $allowed += Util\Tokens::$magicConstants;
for ($x = ($i - 1); $x >= 0; $x--) {
// If we hit a scope opener, the statement has ended
diff --git a/src/Util/Tokens.php b/src/Util/Tokens.php
index d11b193629..bc3a32414a 100644
--- a/src/Util/Tokens.php
+++ b/src/Util/Tokens.php
@@ -589,6 +589,24 @@ final class Tokens
T_TRAIT => T_TRAIT,
];
+ /**
+ * Tokens representing PHP magic constants.
+ *
+ * @var array =>
+ *
+ * @link https://www.php.net/language.constants.predefined PHP Manual on magic constants
+ */
+ public static $magicConstants = [
+ T_CLASS_C => T_CLASS_C,
+ T_DIR => T_DIR,
+ T_FILE => T_FILE,
+ T_FUNC_C => T_FUNC_C,
+ T_LINE => T_LINE,
+ T_METHOD_C => T_METHOD_C,
+ T_NS_C => T_NS_C,
+ T_TRAIT_C => T_TRAIT_C,
+ ];
+
/**
* Given a token, returns the name of the token.
diff --git a/tests/Core/Tokenizer/ShortArrayTest.inc b/tests/Core/Tokenizer/ShortArrayTest.inc
new file mode 100644
index 0000000000..a864869af9
--- /dev/null
+++ b/tests/Core/Tokenizer/ShortArrayTest.inc
@@ -0,0 +1,92 @@
+function_call()[$x];
+
+/* testStaticMethodCallDereferencing */
+$var = ClassName::function_call()[$x];
+
+/* testPropertyDereferencing */
+$var = $obj->property[2];
+
+/* testPropertyDereferencingWithInaccessibleName */
+$var = $ref->{'ref-type'}[1];
+
+/* testStaticPropertyDereferencing */
+$var ClassName::$property[2];
+
+/* testStringDereferencing */
+$var = 'PHP'[1];
+
+/* testStringDereferencingDoubleQuoted */
+$var = "PHP"[$y];
+
+/* testConstantDereferencing */
+$var = MY_CONSTANT[1];
+
+/* testClassConstantDereferencing */
+$var ClassName::CONSTANT_NAME[2];
+
+/* testMagicConstantDereferencing */
+$var = __FILE__[0];
+
+/* testArrayAccessCurlyBraces */
+$var = $array{'key'}['key'];
+
+/* testArrayLiteralDereferencing */
+echo array(1, 2, 3)[0];
+
+echo [1, 2, 3]/* testShortArrayLiteralDereferencing */[0];
+
+/* testClassMemberDereferencingOnInstantiation1 */
+(new foo)[0];
+
+/* testClassMemberDereferencingOnInstantiation2 */
+$a = (new Foo( array(1, array(4, 5), 3) ))[1][0];
+
+/* testClassMemberDereferencingOnClone */
+echo (clone $iterable)[20];
+
+
+/*
+ * Short array brackets.
+ */
+
+/* testShortArrayDeclarationEmpty */
+$array = [];
+
+/* testShortArrayDeclarationWithOneValue */
+$array = [1];
+
+/* testShortArrayDeclarationWithMultipleValues */
+$array = [1, 2, 3];
+
+/* testShortArrayDeclarationWithDereferencing */
+echo [1, 2, 3][0];
+
+/* testShortListDeclaration */
+[ $a, $b ] = $array;
+
+[ $a, $b, /* testNestedListDeclaration */, [$c, $d]] = $array;
+
+/* testArrayWithinFunctionCall */
+$var = functionCall([$x, $y]);
+
+/* testLiveCoding */
+// Intentional parse error. This has to be the last test in the file.
+$array = [
diff --git a/tests/Core/Tokenizer/ShortArrayTest.php b/tests/Core/Tokenizer/ShortArrayTest.php
new file mode 100644
index 0000000000..04aaf3db26
--- /dev/null
+++ b/tests/Core/Tokenizer/ShortArrayTest.php
@@ -0,0 +1,130 @@
+
+ * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600)
+ * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
+ */
+
+namespace PHP_CodeSniffer\Tests\Core\Tokenizer;
+
+use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest;
+
+class ShortArrayTest extends AbstractMethodUnitTest
+{
+
+
+ /**
+ * Test that real square brackets are still tokenized as square brackets.
+ *
+ * @param string $testMarker The comment which prefaces the target token in the test file.
+ *
+ * @dataProvider dataSquareBrackets
+ * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional
+ *
+ * @return void
+ */
+ public function testSquareBrackets($testMarker)
+ {
+ $tokens = self::$phpcsFile->getTokens();
+
+ $opener = $this->getTargetToken($testMarker, [T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY]);
+ $this->assertSame(T_OPEN_SQUARE_BRACKET, $tokens[$opener]['code']);
+ $this->assertSame('T_OPEN_SQUARE_BRACKET', $tokens[$opener]['type']);
+
+ if (isset($tokens[$opener]['bracket_closer']) === true) {
+ $closer = $tokens[$opener]['bracket_closer'];
+ $this->assertSame(T_CLOSE_SQUARE_BRACKET, $tokens[$closer]['code']);
+ $this->assertSame('T_CLOSE_SQUARE_BRACKET', $tokens[$closer]['type']);
+ }
+
+ }//end testSquareBrackets()
+
+
+ /**
+ * Data provider.
+ *
+ * @see testSquareBrackets()
+ *
+ * @return array
+ */
+ public function dataSquareBrackets()
+ {
+ return [
+ ['/* testArrayAccess1 */'],
+ ['/* testArrayAccess2 */'],
+ ['/* testArrayAssignment */'],
+ ['/* testFunctionCallDereferencing */'],
+ ['/* testMethodCallDereferencing */'],
+ ['/* testStaticMethodCallDereferencing */'],
+ ['/* testPropertyDereferencing */'],
+ ['/* testPropertyDereferencingWithInaccessibleName */'],
+ ['/* testStaticPropertyDereferencing */'],
+ ['/* testStringDereferencing */'],
+ ['/* testStringDereferencingDoubleQuoted */'],
+ ['/* testConstantDereferencing */'],
+ ['/* testClassConstantDereferencing */'],
+ ['/* testMagicConstantDereferencing */'],
+ ['/* testArrayAccessCurlyBraces */'],
+ ['/* testArrayLiteralDereferencing */'],
+ ['/* testShortArrayLiteralDereferencing */'],
+ ['/* testClassMemberDereferencingOnInstantiation1 */'],
+ ['/* testClassMemberDereferencingOnInstantiation2 */'],
+ ['/* testClassMemberDereferencingOnClone */'],
+ ['/* testLiveCoding */'],
+ ];
+
+ }//end dataSquareBrackets()
+
+
+ /**
+ * Test that short arrays and short lists are still tokenized as short arrays.
+ *
+ * @param string $testMarker The comment which prefaces the target token in the test file.
+ *
+ * @dataProvider dataShortArrays
+ * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional
+ *
+ * @return void
+ */
+ public function testShortArrays($testMarker)
+ {
+ $tokens = self::$phpcsFile->getTokens();
+
+ $opener = $this->getTargetToken($testMarker, [T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY]);
+ $this->assertSame(T_OPEN_SHORT_ARRAY, $tokens[$opener]['code']);
+ $this->assertSame('T_OPEN_SHORT_ARRAY', $tokens[$opener]['type']);
+
+ if (isset($tokens[$opener]['bracket_closer']) === true) {
+ $closer = $tokens[$opener]['bracket_closer'];
+ $this->assertSame(T_CLOSE_SHORT_ARRAY, $tokens[$closer]['code']);
+ $this->assertSame('T_CLOSE_SHORT_ARRAY', $tokens[$closer]['type']);
+ }
+
+ }//end testShortArrays()
+
+
+ /**
+ * Data provider.
+ *
+ * @see testShortArrays()
+ *
+ * @return array
+ */
+ public function dataShortArrays()
+ {
+ return [
+ ['/* testShortArrayDeclarationEmpty */'],
+ ['/* testShortArrayDeclarationWithOneValue */'],
+ ['/* testShortArrayDeclarationWithMultipleValues */'],
+ ['/* testShortArrayDeclarationWithDereferencing */'],
+ ['/* testShortListDeclaration */'],
+ ['/* testNestedListDeclaration */'],
+ ['/* testArrayWithinFunctionCall */'],
+ ];
+
+ }//end dataShortArrays()
+
+
+}//end class