Skip to content

Commit

Permalink
PHP 8.2 | File::getMethodProperties(): add support for DNF types
Browse files Browse the repository at this point in the history
Includes unit tests.
  • Loading branch information
jrfnl committed Apr 28, 2024
1 parent f41285a commit e3b2f8d
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 12 deletions.
26 changes: 14 additions & 12 deletions src/Files/File.php
Expand Up @@ -1735,18 +1735,20 @@ public function getMethodProperties($stackPtr)
}

$valid = [
T_STRING => T_STRING,
T_CALLABLE => T_CALLABLE,
T_SELF => T_SELF,
T_PARENT => T_PARENT,
T_STATIC => T_STATIC,
T_FALSE => T_FALSE,
T_TRUE => T_TRUE,
T_NULL => T_NULL,
T_NAMESPACE => T_NAMESPACE,
T_NS_SEPARATOR => T_NS_SEPARATOR,
T_TYPE_UNION => T_TYPE_UNION,
T_TYPE_INTERSECTION => T_TYPE_INTERSECTION,
T_STRING => T_STRING,
T_CALLABLE => T_CALLABLE,
T_SELF => T_SELF,
T_PARENT => T_PARENT,
T_STATIC => T_STATIC,
T_FALSE => T_FALSE,
T_TRUE => T_TRUE,
T_NULL => T_NULL,
T_NAMESPACE => T_NAMESPACE,
T_NS_SEPARATOR => T_NS_SEPARATOR,
T_TYPE_UNION => T_TYPE_UNION,
T_TYPE_INTERSECTION => T_TYPE_INTERSECTION,
T_TYPE_OPEN_PARENTHESIS => T_TYPE_OPEN_PARENTHESIS,
T_TYPE_CLOSE_PARENTHESIS => T_TYPE_CLOSE_PARENTHESIS,
];

for ($i = $this->tokens[$stackPtr]['parenthesis_closer']; $i < $this->numTokens; $i++) {
Expand Down
19 changes: 19 additions & 0 deletions tests/Core/File/GetMethodPropertiesTest.inc
Expand Up @@ -170,6 +170,25 @@ function pseudoTypeTrue(): ?true {}
// Intentional fatal error - Type contains both true and false, bool should be used instead, but that's not the concern of the method.
function pseudoTypeFalseAndTrue(): true|false {}

/* testPHP82DNFType */
function hasDNFType() : bool|(Foo&Bar)|string {}

abstract class AbstractClass {
/* testPHP82DNFTypeAbstractMethod */
abstract protected function abstractMethodDNFType() : float|(Foo&Bar);
}

/* testPHP82DNFTypeIllegalNullable */
// Intentional fatal error - nullable operator cannot be combined with DNF.
function illegalNullableDNF(): ?(A&\Pck\B)|bool {}

/* testPHP82DNFTypeClosure */
$closure = function() : object|(namespace\Foo&Countable) {};

/* testPHP82DNFTypeFn */
// Intentional fatal error - void type cannot be combined with DNF.
$arrow = fn() : null|(Partially\Qualified&Traversable)|void => do_something();

/* testNotAFunction */
return true;

Expand Down
130 changes: 130 additions & 0 deletions tests/Core/File/GetMethodPropertiesTest.php
Expand Up @@ -1187,6 +1187,136 @@ public function testPHP82PseudoTypeFalseAndTrue()
}//end testPHP82PseudoTypeFalseAndTrue()


/**
* Verify recognition of PHP 8.2 DNF return type declaration.
*
* @return void
*/
public function testPHP82DNFType()
{
// Offsets are relative to the T_FUNCTION token.
$expected = [
'scope' => 'public',
'scope_specified' => false,
'return_type' => 'bool|(Foo&Bar)|string',
'return_type_token' => 8,
'return_type_end_token' => 16,
'nullable_return_type' => false,
'is_abstract' => false,
'is_final' => false,
'is_static' => false,
'has_body' => true,
];

$this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected);

}//end testPHP82DNFType()


/**
* Verify recognition of PHP 8.2 DNF return type declaration on an abstract method.
*
* @return void
*/
public function testPHP82DNFTypeAbstractMethod()
{
// Offsets are relative to the T_FUNCTION token.
$expected = [
'scope' => 'protected',
'scope_specified' => true,
'return_type' => 'float|(Foo&Bar)',
'return_type_token' => 8,
'return_type_end_token' => 14,
'nullable_return_type' => false,
'is_abstract' => true,
'is_final' => false,
'is_static' => false,
'has_body' => false,
];

$this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected);

}//end testPHP82DNFTypeAbstractMethod()


/**
* Verify recognition of PHP 8.2 DNF return type declaration with illegal nullability.
*
* @return void
*/
public function testPHP82DNFTypeIllegalNullable()
{
// Offsets are relative to the T_FUNCTION token.
$expected = [
'scope' => 'public',
'scope_specified' => false,
'return_type' => '?(A&\Pck\B)|bool',
'return_type_token' => 8,
'return_type_end_token' => 17,
'nullable_return_type' => true,
'is_abstract' => false,
'is_final' => false,
'is_static' => false,
'has_body' => true,
];

$this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected);

}//end testPHP82DNFTypeIllegalNullable()


/**
* Verify recognition of PHP 8.2 DNF return type declaration on a closure.
*
* @return void
*/
public function testPHP82DNFTypeClosure()
{
// Offsets are relative to the T_CLOSURE token.
$expected = [
'scope' => 'public',
'scope_specified' => false,
'return_type' => 'object|(namespace\Foo&Countable)',
'return_type_token' => 6,
'return_type_end_token' => 14,
'nullable_return_type' => false,
'is_abstract' => false,
'is_final' => false,
'is_static' => false,
'has_body' => true,
];

$this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected);

}//end testPHP82DNFTypeClosure()


/**
* Verify recognition of PHP 8.2 DNF return type declaration on an arrow function.
*
* @return void
*/
public function testPHP82DNFTypeFn()
{
// Offsets are relative to the T_FN token.
$expected = [
'scope' => 'public',
'scope_specified' => false,
'return_type' => 'null|(Partially\Qualified&Traversable)|void',
'return_type_token' => 6,
'return_type_end_token' => 16,
'nullable_return_type' => false,
'is_abstract' => false,
'is_final' => false,
'is_static' => false,
'has_body' => true,
];

$this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected);

}//end testPHP82DNFTypeFn()


/**
* Test for incorrect tokenization of array return type declarations in PHPCS < 2.8.0.
*
Expand Down

0 comments on commit e3b2f8d

Please sign in to comment.