Skip to content

Commit

Permalink
PHP 8.1: Added support for "enum" keyword
Browse files Browse the repository at this point in the history
  • Loading branch information
kukulich committed Dec 17, 2021
1 parent 6296b27 commit 106eba3
Show file tree
Hide file tree
Showing 5 changed files with 374 additions and 0 deletions.
6 changes: 6 additions & 0 deletions package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
<file baseinstalldir="" name="ArrayKeywordTest.php" role="test" />
<file baseinstalldir="" name="AttributesTest.inc" role="test" />
<file baseinstalldir="" name="AttributesTest.php" role="test" />
<file baseinstalldir="" name="BackfillEnumTest.inc" role="test" />
<file baseinstalldir="" name="BackfillEnumTest.php" role="test" />
<file baseinstalldir="" name="BackfillExplicitOctalNotationTest.inc" role="test" />
<file baseinstalldir="" name="BackfillExplicitOctalNotationTest.php" role="test" />
<file baseinstalldir="" name="BackfillFnTokenTest.inc" role="test" />
Expand Down Expand Up @@ -2078,6 +2080,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
<install as="CodeSniffer/Core/Tokenizer/ArrayKeywordTest.inc" name="tests/Core/Tokenizer/ArrayKeywordTest.inc" />
<install as="CodeSniffer/Core/Tokenizer/AttributesTest.php" name="tests/Core/Tokenizer/AttributesTest.php" />
<install as="CodeSniffer/Core/Tokenizer/AttributesTest.inc" name="tests/Core/Tokenizer/AttributesTest.inc" />
<install as="CodeSniffer/Core/Tokenizer/BackfillEnumTest.php" name="tests/Core/Tokenizer/BackfillEnumTest.php" />
<install as="CodeSniffer/Core/Tokenizer/BackfillEnumTest.inc" name="tests/Core/Tokenizer/BackfillEnumTest.inc" />
<install as="CodeSniffer/Core/Tokenizer/BackfillExplicitOctalNotationTest.php" name="tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.php" />
<install as="CodeSniffer/Core/Tokenizer/BackfillExplicitOctalNotationTest.inc" name="tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.inc" />
<install as="CodeSniffer/Core/Tokenizer/BackfillFnTokenTest.php" name="tests/Core/Tokenizer/BackfillFnTokenTest.php" />
Expand Down Expand Up @@ -2172,6 +2176,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
<install as="CodeSniffer/Core/Tokenizer/ArrayKeywordTest.inc" name="tests/Core/Tokenizer/ArrayKeywordTest.inc" />
<install as="CodeSniffer/Core/Tokenizer/AttributesTest.php" name="tests/Core/Tokenizer/AttributesTest.php" />
<install as="CodeSniffer/Core/Tokenizer/AttributesTest.inc" name="tests/Core/Tokenizer/AttributesTest.inc" />
<install as="CodeSniffer/Core/Tokenizer/BackfillEnumTest.php" name="tests/Core/Tokenizer/BackfillEnumTest.php" />
<install as="CodeSniffer/Core/Tokenizer/BackfillEnumTest.inc" name="tests/Core/Tokenizer/BackfillEnumTest.inc" />
<install as="CodeSniffer/Core/Tokenizer/BackfillExplicitOctalNotationTest.php" name="tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.php" />
<install as="CodeSniffer/Core/Tokenizer/BackfillExplicitOctalNotationTest.inc" name="tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.inc" />
<install as="CodeSniffer/Core/Tokenizer/BackfillFnTokenTest.php" name="tests/Core/Tokenizer/BackfillFnTokenTest.php" />
Expand Down
45 changes: 45 additions & 0 deletions src/Tokenizers/PHP.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@ class PHP extends Tokenizer
'shared' => false,
'with' => [],
],
T_ENUM => [
'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
'strict' => true,
'shared' => false,
'with' => [],
],
T_USE => [
'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
Expand Down Expand Up @@ -339,6 +346,7 @@ class PHP extends Tokenizer
T_ENDIF => 5,
T_ENDSWITCH => 9,
T_ENDWHILE => 8,
T_ENUM => 4,
T_EVAL => 4,
T_EXTENDS => 7,
T_FILE => 8,
Expand Down Expand Up @@ -467,6 +475,7 @@ class PHP extends Tokenizer
T_CLASS => true,
T_INTERFACE => true,
T_TRAIT => true,
T_ENUM => true,
T_EXTENDS => true,
T_IMPLEMENTS => true,
T_ATTRIBUTE => true,
Expand Down Expand Up @@ -894,6 +903,42 @@ protected function tokenize($string)
continue;
}//end if

/*
Enum keyword for PHP < 8.1
*/

if ($tokenIsArray === true
&& $token[0] === T_STRING
&& strtolower($token[1]) === 'enum'
) {
// Get the next non-empty token.
for ($i = ($stackPtr + 1); $i < $numTokens; $i++) {
if (is_array($tokens[$i]) === false
|| isset(Util\Tokens::$emptyTokens[$tokens[$i][0]]) === false
) {
break;
}
}

if (isset($tokens[$i]) === true
&& is_array($tokens[$i]) === true
&& $tokens[$i][0] === T_STRING
) {
$newToken = [];
$newToken['code'] = T_ENUM;
$newToken['type'] = 'T_ENUM';
$newToken['content'] = $token[1];
$finalTokens[$newStackPtr] = $newToken;

if (PHP_CODESNIFFER_VERBOSITY > 1) {
echo "\t\t* token $stackPtr changed from T_STRING to T_ENUM".PHP_EOL;
}

$newStackPtr++;
continue;
}
}//end if

/*
As of PHP 8.0 fully qualified, partially qualified and namespace relative
identifier names are tokenized differently.
Expand Down
7 changes: 7 additions & 0 deletions src/Util/Tokens.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@
define('T_READONLY', 'PHPCS_T_READONLY');
}

if (defined('T_ENUM') === false) {
define('T_ENUM', 'PHPCS_T_ENUM');
}

// Tokens used for parsing doc blocks.
define('T_DOC_COMMENT_STAR', 'PHPCS_T_DOC_COMMENT_STAR');
define('T_DOC_COMMENT_WHITESPACE', 'PHPCS_T_DOC_COMMENT_WHITESPACE');
Expand Down Expand Up @@ -194,6 +198,7 @@ final class Tokens
T_CLASS => 1000,
T_INTERFACE => 1000,
T_TRAIT => 1000,
T_ENUM => 1000,
T_NAMESPACE => 1000,
T_FUNCTION => 100,
T_CLOSURE => 100,
Expand Down Expand Up @@ -419,6 +424,7 @@ final class Tokens
T_ANON_CLASS => T_ANON_CLASS,
T_INTERFACE => T_INTERFACE,
T_TRAIT => T_TRAIT,
T_ENUM => T_ENUM,
T_NAMESPACE => T_NAMESPACE,
T_FUNCTION => T_FUNCTION,
T_CLOSURE => T_CLOSURE,
Expand Down Expand Up @@ -633,6 +639,7 @@ final class Tokens
T_ANON_CLASS => T_ANON_CLASS,
T_INTERFACE => T_INTERFACE,
T_TRAIT => T_TRAIT,
T_ENUM => T_ENUM,
];

/**
Expand Down
91 changes: 91 additions & 0 deletions tests/Core/Tokenizer/BackfillEnumTest.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

/* testPureEnum */
enum Foo
{
case SOME_CASE;
}

/* testBackedIntEnum */
enum Boo: int {
case ONE = 1;
case TWO = 1;
}

/* testBackedStringEnum */
enum Hoo: string
{
case ONE = 'one';
case TWO = 'two';
}

/* testComplexEnum */
enum ComplexEnum: int implements SomeInterface
{
use SomeTrait {
traitMethod as enumMethod;
}

const SOME_CONSTANT = true;

case ONE = 1;

public function someMethod(): bool
{
}
}

/* testEnumWithEnumAsClassName */
enum /* testEnumAsClassNameAfterEnumKeyword */ Enum {}

/* testEnumIsCaseInsensitive */
EnUm Enum {}

/* testEnumUsedAsClassName */
class Enum {
/* testEnumUsedAsClassConstantName */
const ENUM = 'enum';

/* testEnumUsedAsMethodName */
public function enum() {
// Do something.

/* testEnumUsedAsPropertyName */
$this->enum = 'foo';
}
}

/* testEnumUsedAsFunctionName */
function enum()
{
}

/* testDeclarationContainingComment */
enum /* comment */ Name
{
case SOME_CASE;
}

/* testEnumUsedAsNamespaceName */
namespace Enum;
/* testEnumUsedAsPartOfNamespaceName */
namespace My\Enum\Collection;
/* testEnumUsedInObjectInitialization */
$obj = new Enum;
/* testEnumAsFunctionCall */
$var = enum($a, $b);
/* testEnumAsFunctionCallWithNamespace */
var = namespace\enum();
/* testClassConstantFetchWithEnumAsClassName */
echo Enum::CONSTANT;
/* testClassConstantFetchWithEnumAsConstantName */
echo ClassName::ENUM;

/* testParseErrorMissingName */
enum {
case SOME_CASE;
}

/* testParseErrorLiveCoding */
// This must be the last test in the file.
enum
Loading

0 comments on commit 106eba3

Please sign in to comment.