Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP 8.1: Added support for enum keyword #3478

Merged
merged 1 commit into from
Jan 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,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 @@ -2092,6 +2094,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 @@ -2188,6 +2192,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 @@ -952,6 +961,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;
}
kukulich marked this conversation as resolved.
Show resolved Hide resolved

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

/*
As of PHP 8.0 fully qualified, partially qualified and namespace relative
identifier names are tokenized differently.
Expand Down
8 changes: 8 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,
kukulich marked this conversation as resolved.
Show resolved Hide resolved
];

/**
Expand Down Expand Up @@ -684,6 +691,7 @@ final class Tokens
T_ENDIF => T_ENDIF,
T_ENDSWITCH => T_ENDSWITCH,
T_ENDWHILE => T_ENDWHILE,
T_ENUM => T_ENUM,
T_EXIT => T_EXIT,
T_EXTENDS => T_EXTENDS,
T_FINAL => T_FINAL,
Expand Down
95 changes: 95 additions & 0 deletions tests/Core/Tokenizer/BackfillEnumTest.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?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;
}

enum /* testEnumUsedAsEnumName */ Enum
{
}

/* 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